kroman82 Posted February 25, 2025 Posted February 25, 2025 yes, I'm want to: Quote store the public key blob in a variable or constant within you script and use it to encrypt data I'm tryed to find internal function by this keyword __CryptoNG_BcryptImportKeyPair but can't find...
kroman82 Posted February 25, 2025 Posted February 25, 2025 (edited) sorry, I'm found that... Edited February 25, 2025 by kroman82
argumentum Posted February 25, 2025 Posted February 25, 2025 16 minutes ago, kroman82 said: sorry, I'm found that... ... Func __CryptoNG_BcryptImportKeyPair($hAlgorithmProvider, $sKeyBlobFile, $sKeyBlobType, $xKeyBlob = Binary("")) If $__gbDebugging Then _DebugOut(@CRLF & "Function: __CryptoNG_BcryptImportKeyPair()") Local $aResult[0] Local $iError = 0, _ $iStatusCode = 0 Local $tBuffer = "" Local $hFile = -1, _ $hKey = -1 ;~ Local $xKeyBlob = Binary("") If $xKeyBlob = Binary("") Then ;Make sure file exists If Not FileExists($sKeyBlobFile) Then Return SetError(3, 0, "") ;Read binary blob file $hFile = FileOpen($sKeyBlobFile, $FO_BINARY) If $hFile = -1 Then Return SetError(4, 0, "") $xKeyBlob = FileRead($hFile) FileClose($hFile) EndIf ... Placing $xKeyBlob as a parameter I think would work nicely kroman82 and Werty 2 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted February 25, 2025 Posted February 25, 2025 ..then again: ... Func __CryptoNG_BcryptImportKeyPair($hAlgorithmProvider, $sKeyBlobFile, $sKeyBlobType) If $__gbDebugging Then _DebugOut(@CRLF & "Function: __CryptoNG_BcryptImportKeyPair()") Local $aResult[0] Local $iError = 0, _ $iStatusCode = 0 Local $tBuffer = "" Local $hFile = -1, _ $hKey = -1 Local $xKeyBlob = Binary("") If StringLeft($sKeyBlobFile, 3) = "ECS" Or StringLeft($sKeyBlobFile, 3) = "RSA" Then $xKeyBlob = $sKeyBlobFile Else ;Make sure file exists If Not FileExists($sKeyBlobFile) Then Return SetError(3, 0, "") ;Read binary blob file $hFile = FileOpen($sKeyBlobFile, $FO_BINARY) If $hFile = -1 Then Return SetError(4, 0, "") $xKeyBlob = FileRead($hFile) FileClose($hFile) EndIf ... these blob files start with a header that is ECS or RSA and no filename will start as such. This idea will be easier to implement script wide. Am just looking at it. Never used the UDF yet. Just sharing ideas. Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
argumentum Posted February 25, 2025 Posted February 25, 2025 (edited) ok, here is my running code/idea: <removed> I will remove this file in a few days to save in forum file space. I hope this is all you are after @kroman82 ( I worked on it because I've got things to do but I don't wanna do 'em but am anxious 🤪 ) Edit: removed zip. New v2.4.0 can now accept the public/private key blob as either a string containing the file path to the key blob file or as binary data containing the key blob itself. Edited February 26, 2025 by argumentum removed zip file kroman82 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
kroman82 Posted February 25, 2025 Posted February 25, 2025 Thank you very much argumentum ! argumentum 1
konya Posted February 27, 2025 Posted February 27, 2025 I use both Crypt.au3 and CryptoNG.au3 and often operate conversion and creation and non-file usage. I would like to share some codes that I have improved or generated, hoping to be helpful to you. #include "..\CryptoNG.au3" #include <bignum.au3> #include <string.au3> #include <array.au3> Local $c_data = FileOpenDialog("Select a license data", @ScriptDir & "\", "c data (*.*)", 1) If @error Then MsgBox(4096,"","No File(s) choose") Exit EndIf Local $hFileOpen = FileOpen($c_data, 0) Local $c = FileRead($hFileOpen) $Private_c =_WinAPI_Base64Decode($c) $n_binary = Binary("0xput in data") $Public_key = Create_to_Blob(@ScriptDir&"\Test.blob","public", 2048, 65537, $n_binary, 0x0, 0x0, 0, 0 ) $m = _CryptoNG_RSA_EncryptData($Private_c , $Public_key, $CNG_BCRYPT_PAD_NONE, Default, "binary" ) ;Read_to_Blob(@ScriptDir&"\example_legacy_privatekey.blob", "Private", "Legacy") ;Read_to_Blob(@ScriptDir&"\example_legacy_publickey.blob", "Public", "Legacy") ;Read_to_Blob(@ScriptDir&"\example_rsa_privatekey.blob","Private") ;Read_to_Blob(@ScriptDir&"\example_rsa_publickey.blob","public") ;Create_to_Blob(@ScriptDir&"\Test20250227.blob","public",2048,65537,Binary("0x" & _BigHex_Swap_endian("092E57E9A31BB37F89222D15A2449594A4ED5705BF395A4469218881CA8C8A27437F7CE2B1ADEF8D93AE19BF381489DD7D06ED674FF945BF932F3FD81CEDB875F8A677CD4A4468A5DF249B9C0611F5E31DE60DBA86BCB69C38D0EED3931A61E379136E52FB7D39B30B5FA29CA5205D8B6A8101E666779EF3D99B196B4F54AA43F682B53FA5BE8986A7086D4C75975DCB22640DD8ACFAEBA7C8D72058AC997F4EB72F824FD45C55C29C0834AB0D629B56F191A4BB16CDA0694141DC64DAACEF8F923FDC8F3734FA5CE59E7034C2D9237358084259D10134C0A13C2098847630B656179B1F7DB61674D1B705A10E41A7F215D0D865A46E6BC2850642BA413C55C5")),Binary("0x" & _BigHex_Swap_endian("C7C6000BB7C3E10D0440AB2BE592D5F0A7D7899A721A256C0554CF3989D77C1AC1BCC27F9CF4884033A16D0CA8B478A9B2DCB92B6A5993AD3E303D971F1539C8AD306697BA08B340EEAD98D4C462B5E77DF9615F0DA5ED5DFA5B6167AD19D6C6A06AAD1ED71E8E1B7A99F9F3E3838DE7F51F0B2C5AE3D2B784C55A29AAB8A8CF")),Binary("0x" & _BigHex_Swap_endian("AF54BA9A2567F5AD9BC29158786F9E7264DDB487E8750B1E2455121383CE487EA2F1E43842D42864830063FCD906B521F6DE05CACBD8CC5886486DFA51DFB6D404F5168F26B5508F6F71D937C27A0EF90300A60B9293AB00B3D2917C65D2B7AFDC5635F0AC721622307DF3D846F501CA1125D567D4178929CFF93281202345F3")),0,1,"Legacy") ;Create_to_Blob(@ScriptDir&"\Test20250227.blob","PRIVATE",2048,65537,Binary("0x" & _BigHex_Swap_endian("092E57E9A31BB37F89222D15A2449594A4ED5705BF395A4469218881CA8C8A27437F7CE2B1ADEF8D93AE19BF381489DD7D06ED674FF945BF932F3FD81CEDB875F8A677CD4A4468A5DF249B9C0611F5E31DE60DBA86BCB69C38D0EED3931A61E379136E52FB7D39B30B5FA29CA5205D8B6A8101E666779EF3D99B196B4F54AA43F682B53FA5BE8986A7086D4C75975DCB22640DD8ACFAEBA7C8D72058AC997F4EB72F824FD45C55C29C0834AB0D629B56F191A4BB16CDA0694141DC64DAACEF8F923FDC8F3734FA5CE59E7034C2D9237358084259D10134C0A13C2098847630B656179B1F7DB61674D1B705A10E41A7F215D0D865A46E6BC2850642BA413C55C5")),Binary("0x" & _BigHex_Swap_endian("C7C6000BB7C3E10D0440AB2BE592D5F0A7D7899A721A256C0554CF3989D77C1AC1BCC27F9CF4884033A16D0CA8B478A9B2DCB92B6A5993AD3E303D971F1539C8AD306697BA08B340EEAD98D4C462B5E77DF9615F0DA5ED5DFA5B6167AD19D6C6A06AAD1ED71E8E1B7A99F9F3E3838DE7F51F0B2C5AE3D2B784C55A29AAB8A8CF")),Binary("0x" & _BigHex_Swap_endian("AF54BA9A2567F5AD9BC29158786F9E7264DDB487E8750B1E2455121383CE487EA2F1E43842D42864830063FCD906B521F6DE05CACBD8CC5886486DFA51DFB6D404F5168F26B5508F6F71D937C27A0EF90300A60B9293AB00B3D2917C65D2B7AFDC5635F0AC721622307DF3D846F501CA1125D567D4178929CFF93281202345F3")),0,1,"Legacy") expandcollapse popupGlobal Const $tagRSAPUBKEY = _ "align 1;" & _ "char magic[4];" & _ "uint bitlen;" & _ "uint PubExpLength;" & _ "uint ModulusLength;" & _ "uint PLength;" & _ "uint QLength;" & _ "byte PubExp[3];" & _ "byte Modulus[1];" Global Const $tagRSAPRIVATEKEY = _ "align 1;" & _ "char magic[4];" & _ "uint bitlen;" & _ "uint PubExpLength;" & _ "uint ModulusLength;" & _ "uint PLength;" & _ "uint QLength;" & _ "byte PubExp[3];" & _ "byte Modulus[1];" & _ "byte P[1];" & _ "byte q[1];" Global Const $tagRSAPRIVATEKEY_Legacy = _ "byte bType[1];" & _ "byte bVersion[1];" & _ "word reserved[1];" & _ "byte aiKeyAlg[4];" & _ "char magic[4];" & _ "uint bitlen;" & _ "byte PubExp[4];" & _ "byte Modulus[1];" & _ "byte p[1];" & _ "byte q[1];" & _ "byte exponent1[1];" & _ "byte exponent2[1];" & _ "byte coefficient[1];" & _ "byte privateExponent[1];" Global Const $tagRSAPUBKEY_Legacy = _ "byte bType[1];" & _ "byte bVersion[1];" & _ "word reserved[1];" & _ "byte aiKeyAlg[4];" & _ "char magic[4];" & _ "uint bitlen;" & _ "byte PubExp[4];" & _ "byte Modulus[1];" Func _BigNum_inverse($a, $b) $result = 0 Local $array[0][2], $cc = 1 While 1 If Mod($cc, 2) = 1 Then _ArrayAdd($array, $b & "|" & $a) Else _ArrayAdd($array, $a & "|" & $b) EndIf $cc += 1 $result = _BigNum_Mod($a, $b) If $result <> 0 Then $a = $b $b = $result Else ExitLoop EndIf WEnd $cc = 1 Local $d = "", $k = "" For $i = UBound($array) - 1 To 0 Step -1 If $cc = 1 Then If $array[$i][0] = 1 Then $d = 1 Else $d = 1 $k = $array[$i][0] - 1 EndIf EndIf If $cc <> 1 Then If $k = "" Then $k = _BigNum_Div((_BigNum_Sub(_BigNum_Mul($array[$i][0], $d), 1)), $array[$i][1]) Else $d = _BigNum_Div((_BigNum_Add(_BigNum_Mul($array[$i][1], $k), 1)), $array[$i][0]) $k = "" EndIf EndIf $cc += 1 Next Return $d EndFunc Func _BigHex_Swap_endian($data) $result = "" if IsBinary($data) Then $data = Hex($data,BinaryLen($data)) EndIf if Mod(StringLen($data),2) <> 0 Then $data = "0" & $data EndIf for $i = 1 to StringLen($data) step 2 $result = StringMid($data,$i,2) & $result Next Return $result EndFunc Func _BigNum_ToBase2($iDec, $base = 16 , $checkfirstzero = 0) $base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;base64 ;Sexagesimal $base60_2 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx" ;sexagesimal $base32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" ;base32 $base24 = "0123456789ABCDEFGHJKLMNP" ;base24 $base16 = "0123456789ABCDEF" ;hex ;Duodecimal system or dozenal $base12 = "0123456789AB" ;duodecimal $base10 = "0123456789" ;base10 $base8 = "01234567" ;oct $base2 = "01" ;binary If $base = 2 Then $Symbol = $base2 ElseIf $base = 8 Then $Symbol = $base8 ElseIf $base = 10 Then $Symbol = $base10 ElseIf $base = 16 Then $Symbol = $base16 ElseIf $base = 60 Then $Symbol = $base60_2 ElseIf $base = 64 Then $Symbol = $base64 EndIf Local $Out, $ost $Symbol = StringSplit($Symbol, '') If @error Or $Symbol[0] < 2 Then Return SetError(1, 0, $iDec) Do $ost = _BigNum_Mod($iDec, $Symbol[0]) $iDec = _BigNum_Div(_BigNum_Sub($iDec, $ost), $Symbol[0]) $Out = $Symbol[$ost + 1] & $Out Until Not Number($iDec) if $checkfirstzero = 1 Then if Mod(StringLen($Out),2) <> 0 Then $Out = "0" & $Out EndIf EndIf Return SetError(0, $Symbol[0], $Out) EndFunc Func _BigHex_ToBase2($sDecimal, $iBase) Local $vDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!""#$%&'()*+,-./:;<=>?@[\]^_`{|}~" ; 96 ASCII symbols, use Unicode for more 94個字元 If $iBase > StringLen($vDigits) Then SetError(1, 0, 0) $vDigits = StringSplit($vDigits, '', 2) Local $sResult = 0 For $i = 1 To StringLen($sDecimal) $nn = _ArraySearch($vDigits, StringMid($sDecimal, $i, 1)) $sResult = _BigNum_Add(_BigNum_Mul($iBase, $sResult), $nn) Next Return $sResult EndFunc Func Read_to_Blob($key_path ,$tag = "Public", $tag2 = "new" , $type = "File" , $showdata = 1) Local $returndata[2] if $type <> "File" Then $blob_b = $key_path Else Local $hFile = FileOpen($key_path,$FO_BINARY) Local $blob_b = FileRead($hFile) FileClose($hFile) EndIf Local $blob_handle = DllStructCreate("byte a["&BinaryLen($blob_b)&"];") $blob_handle.a = $blob_b if $tag2 = "new" Then if $tag = "Public" Then Local $blob_data = DllStructCreate($tagRSAPUBKEY,DllStructGetPtr($blob_handle)) Local $tagRSAPUBKEY2 = StringReplace($tagRSAPUBKEY,"Modulus[1]","Modulus["&$blob_data.bitlen/8&"]") $blob_data = DllStructCreate($tagRSAPUBKEY2,DllStructGetPtr($blob_handle)) $returndata[1] = $tagRSAPUBKEY2 if $showdata = 1 Then _WinAPI_DisplayStruct($blob_data,$tagRSAPUBKEY2) EndIf Else Local $blob_data = DllStructCreate($tagRSAPRIVATEKEY,DllStructGetPtr($blob_handle)) Local $tagRSAPRIVATEKEY2 = StringReplace($tagRSAPRIVATEKEY,"Modulus[1]","Modulus["&$blob_data.bitlen/8&"]") $tagRSAPRIVATEKEY2 = StringReplace($tagRSAPRIVATEKEY2,"p[1]","p["&$blob_data.bitlen/8/2&"]") $tagRSAPRIVATEKEY2 = StringReplace($tagRSAPRIVATEKEY2,"q[1]","q["&$blob_data.bitlen/8/2&"]") $blob_data = DllStructCreate($tagRSAPRIVATEKEY2,DllStructGetPtr($blob_handle)) $returndata[1] = $tagRSAPRIVATEKEY2 if $showdata = 1 Then _WinAPI_DisplayStruct($blob_data,$tagRSAPRIVATEKEY2) EndIf EndIf Else if $tag = "Public" Then Local $blob_data = DllStructCreate($tagRSAPUBKEY_Legacy,DllStructGetPtr($blob_handle)) Local $tagRSAPUBKEY2_Legacy = StringReplace($tagRSAPUBKEY_Legacy,"Modulus[1]","Modulus["&$blob_data.bitlen/8&"]") $blob_data = DllStructCreate($tagRSAPUBKEY2_Legacy,DllStructGetPtr($blob_handle)) $returndata[1] = $tagRSAPUBKEY2_Legacy if $showdata = 1 Then _WinAPI_DisplayStruct($blob_data,$tagRSAPUBKEY2_Legacy) EndIf Else Local $blob_data = DllStructCreate($tagRSAPRIVATEKEY_Legacy,DllStructGetPtr($blob_handle)) Local $tagRSAPRIVATEKEY2_Legacy = StringReplace($tagRSAPRIVATEKEY_Legacy,"Modulus[1]","Modulus["&$blob_data.bitlen/8&"]") $tagRSAPRIVATEKEY2_Legacy = StringReplace($tagRSAPRIVATEKEY2_Legacy,"p[1]","p["&$blob_data.bitlen/8/2&"]") $tagRSAPRIVATEKEY2_Legacy = StringReplace($tagRSAPRIVATEKEY2_Legacy,"q[1]","q["&$blob_data.bitlen/8/2&"]") $tagRSAPRIVATEKEY2_Legacy = StringReplace($tagRSAPRIVATEKEY2_Legacy,"exponent1[1]","exponent1["&$blob_data.bitlen/8/2&"]") $tagRSAPRIVATEKEY2_Legacy = StringReplace($tagRSAPRIVATEKEY2_Legacy,"exponent2[1]","exponent2["&$blob_data.bitlen/8/2&"]") $tagRSAPRIVATEKEY2_Legacy = StringReplace($tagRSAPRIVATEKEY2_Legacy,"coefficient[1]","coefficient["&$blob_data.bitlen/8/2&"]") $tagRSAPRIVATEKEY2_Legacy = StringReplace($tagRSAPRIVATEKEY2_Legacy,"privateExponent[1]","privateExponent["&$blob_data.bitlen/8&"]") $blob_data = DllStructCreate($tagRSAPRIVATEKEY2_Legacy,DllStructGetPtr($blob_handle)) $returndata[1] = $tagRSAPRIVATEKEY2_Legacy if $showdata = 1 Then _WinAPI_DisplayStruct($blob_data,$tagRSAPRIVATEKEY2_Legacy) EndIf EndIf EndIf $returndata[0] = $blob_data Return $returndata EndFunc Func Create_to_Blob($key_path,$tag = "Public" , $bitlen = 2048, $e = 65537, $Modulus = Binary("0x00"), $p = Binary("0x00"), $q = Binary("0x00") ,$write_or_binary = 1, $show = 0, $tag2 = "new") if $tag2 = "new" Then if $tag = "Public" Then Local $tagRSAPUBKEY2 = StringReplace($tagRSAPUBKEY,"Modulus[1]","Modulus["&$bitlen/8&"]") Local $blob_data = DllStructCreate($tagRSAPUBKEY2) $blob_data.magic = "RSA1" $blob_data.bitlen = $bitlen $blob_data.PubExpLength = 3 $blob_data.ModulusLength = $blob_data.bitlen/8 $blob_data.PLength = 0 $blob_data.QLength = 0 $blob_data.PubExp = $e $blob_data.Modulus = $Modulus if $show = 1 Then _WinAPI_DisplayStruct($blob_data,$tagRSAPUBKEY2) EndIf Else Local $tagRSAPRIVATEKEY2 = StringReplace($tagRSAPRIVATEKEY,"Modulus[1]","Modulus["&$bitlen/8&"]") $tagRSAPRIVATEKEY2 = StringReplace($tagRSAPRIVATEKEY2,"p[1]","p["&$bitlen/8/2&"]") $tagRSAPRIVATEKEY2 = StringReplace($tagRSAPRIVATEKEY2,"q[1]","q["&$bitlen/8/2&"]") Local $blob_data = DllStructCreate($tagRSAPRIVATEKEY2) $blob_data.magic = "RSA2" $blob_data.bitlen = $bitlen $blob_data.PubExpLength = 3 $blob_data.ModulusLength = $blob_data.bitlen/8 $blob_data.PLength = $blob_data.bitlen/8/2 $blob_data.QLength = $blob_data.bitlen/8/2 $blob_data.PubExp = $e $blob_data.Modulus = $Modulus $blob_data.p = $p $blob_data.q = $q if $show = 1 then _WinAPI_DisplayStruct($blob_data,$tagRSAPRIVATEKEY2) EndIf EndIf Else if $tag = "Public" Then Local $tagRSAPUBKEY_Legacy2 = StringReplace($tagRSAPUBKEY_Legacy,"Modulus[1]","Modulus["&$bitlen/8&"]") Local $blob_data = DllStructCreate($tagRSAPUBKEY_Legacy2) $blob_data.bType = 0x06 $blob_data.bVersion = 0x02 $blob_data.aiKeyAlg = Binary("0x00A40000") $blob_data.magic = "RSA1" $blob_data.bitlen = $bitlen $blob_data.PubExp = Binary("0x" & _BigHex_Swap_endian(_BigNum_ToBase2($e,16,1))) $blob_data.Modulus = Binary("0x" & _BigHex_Swap_endian($Modulus)) if $show = 1 Then _WinAPI_DisplayStruct($blob_data,$tagRSAPUBKEY_Legacy2) EndIf Else Local $tagRSAPRIVATEKEY_Legacy2 = StringReplace($tagRSAPRIVATEKEY_Legacy,"Modulus[1]","Modulus["&$bitlen/8&"]") $tagRSAPRIVATEKEY_Legacy2 = StringReplace($tagRSAPRIVATEKEY_Legacy2,"p[1]","p["&$bitlen/8/2&"]") $tagRSAPRIVATEKEY_Legacy2 = StringReplace($tagRSAPRIVATEKEY_Legacy2,"q[1]","q["&$bitlen/8/2&"]") $tagRSAPRIVATEKEY_Legacy2 = StringReplace($tagRSAPRIVATEKEY_Legacy2,"exponent1[1]","exponent1["&$bitlen/8/2&"]") $tagRSAPRIVATEKEY_Legacy2 = StringReplace($tagRSAPRIVATEKEY_Legacy2,"exponent2[1]","exponent2["&$bitlen/8/2&"]") $tagRSAPRIVATEKEY_Legacy2 = StringReplace($tagRSAPRIVATEKEY_Legacy2,"coefficient[1]","coefficient["&$bitlen/8/2&"]") $tagRSAPRIVATEKEY_Legacy2 = StringReplace($tagRSAPRIVATEKEY_Legacy2,"privateExponent[1]","privateExponent["&$bitlen/8&"]") Local $blob_data = DllStructCreate($tagRSAPRIVATEKEY_Legacy2) $blob_data.bType = 0x07 $blob_data.bVersion = 0x02 $blob_data.aiKeyAlg = Binary("0x00A40000") $blob_data.magic = "RSA2" $blob_data.bitlen = $bitlen $blob_data.PubExp = Binary("0x" & _BigHex_Swap_endian(_BigNum_ToBase2($e,16,1))) $blob_data.Modulus = Binary("0x" & _BigHex_Swap_endian($Modulus)) $blob_data.p = Binary("0x" & _BigHex_Swap_endian($p)) $blob_data.q = Binary("0x" & _BigHex_Swap_endian($q)) Local $D = _BigNum_inverse(_BigNum_Mul(_BigNum_Sub(_BigHex_ToBase2(Hex($p), 16),1),_BigNum_Sub(_BigHex_ToBase2(Hex($q), 16),1)),$e) $blob_data.exponent1 = Binary("0x" &_BigHex_Swap_endian(_BigNum_ToBase2(_BigNum_mod($D,_BigNum_Sub(_BigHex_ToBase2(Hex($p), 16),1)),16,1))) $blob_data.exponent2 = Binary("0x" &_BigHex_Swap_endian(_BigNum_ToBase2(_BigNum_mod($D,_BigNum_Sub(_BigHex_ToBase2(Hex($q), 16),1)),16,1))) $blob_data.coefficient = Binary("0x" &_BigHex_Swap_endian(_BigNum_ToBase2(_BigNum_inverse(_BigHex_ToBase2(Hex($p), 16) , _BigHex_ToBase2(Hex($q), 16)),16,1))) $blob_data.privateExponent = Binary("0x" &_BigHex_Swap_endian(_BigNum_ToBase2($D,16,1))) if $show = 1 then _WinAPI_DisplayStruct($blob_data,$tagRSAPRIVATEKEY_Legacy2) EndIf EndIf EndIf Local $blob_binary = DllStructCreate("byte a["&DllStructGetSize($blob_data)&"];",DllStructGetPtr($blob_data)) if $write_or_binary = 1 Then $hFile = FileOpen($key_path,$FO_BINARY+$FO_OVERWRITE) FileWrite($hFile,$blob_binary.a) FileClose($hFile) Else Return $blob_binary.a EndIf EndFunc Func __CryptoNG_BcryptImportKeyPair($hAlgorithmProvider, $sKeyBlobFile, $sKeyBlobType, $Key_type = "file" ) If $__gbDebugging Then _DebugOut(@CRLF & "Function: __CryptoNG_BcryptImportKeyPair()") Local $aResult[0] Local $iError = 0, _ $iStatusCode = 0 Local $tBuffer = "" Local $hFile = -1, _ $hKey = -1 Local $xKeyBlob = Binary("") ;Make sure file exists if $Key_type = "file" Then If Not FileExists($sKeyBlobFile) Then Return SetError(3, 0, "") ;Read binary blob file $hFile = FileOpen($sKeyBlobFile, $FO_BINARY) If $hFile = -1 Then Return SetError(4, 0, "") $xKeyBlob = FileRead($hFile) FileClose($hFile) Else $xKeyBlob = $sKeyBlobFile EndIf ;Create a binary buffer, containing key blob, to pass to function $tBuffer = DllStructCreate(StringFormat("byte data[%i]", BinaryLen($xKeyBlob))) $tBuffer.data = $xKeyBlob If $__gbDebugging Then _DebugReportVar("Public/Private Key Blob", $tBuffer.data) ;Import key pair $aResult = DllCall(__CryptoNG_GetBcryptDllHandle(), "int", "BCryptImportKeyPair", _ "handle", $hAlgorithmProvider, _ "handle", Null, _ "wstr", $sKeyBlobType, _ "handle*", Null, _ "struct*", $tBuffer, _ "ulong", DllStructGetSize($tBuffer), _ "ulong", $CNG_BCRYPT_NO_KEY_VALIDATION _ ) If @error Then $iError = @error $__gsLastErrorMessage = __CryptoNG_DllCallErrorMessage($iError) Return SetError(1, $iError, "") EndIf If $__gbDebugging Then _DebugReportVar("BCryptImportKeyPair $aResult", $aResult) ;Get returned values from dllcall $iStatusCode = $aResult[0] $hKey = $aResult[4] ;Check status code from dllcall If $iStatusCode <> $CNG_STATUS_SUCCESS Then $__gsLastErrorMessage = __CryptoNG_StatusMessage($iStatusCode) Return SetError(2, $iStatusCode, "") EndIf ;All is good, return handle pointer Return $hKey EndFunc Func _CryptoNG_RSA_EncryptData($sText, $sPublicKeyBlobFile, $iPadding = Default, $sProvider = Default ,$Key_type = "file") If $__gbDebugging Then _DebugOut(@CRLF & "Function: _CryptoNG_RSA_EncryptData()") Local $hAlgorithmProvider = -1, _ $hEncryptionKey = -1 Local $xEncryptedText = "" ;Resolve defaults If $sProvider = Default Then $sProvider = "Microsoft Primitive Provider" If $iPadding = Default Then $iPadding = $CNG_BCRYPT_PAD_PKCS1 ;Make sure that text is not blank If $sText = "" Then $__gsLastErrorMessage = "Invalid parameter - Text cannot be blank." Return SetError(-1, 0, "") EndIf ;Make sure that key blob file exists if $Key_type = "file" Then If Not FileExists($sPublicKeyBlobFile) Then $__gsLastErrorMessage = "Public key blob file does not exist." Return SetError(-2, 0, "") EndIf EndIf ;Open algorithm provider $hAlgorithmProvider = __CryptoNG_BCryptOpenEncryptionAlgorithmProvider($CNG_BCRYPT_RSA_ALGORITHM, $sProvider) If @error Then Return SetError(2, 0, "") ;Import rsa public key $hEncryptionKey = __CryptoNG_BcryptImportKeyPair($hAlgorithmProvider, $sPublicKeyBlobFile, $CNG_BCRYPT_RSAPUBLIC_BLOB, $Key_type) If @error Then If $hAlgorithmProvider <> -1 Then __CryptoNG_BcryptCloseAlgorithmProvider($hAlgorithmProvider) Return SetError(3, 0, "") EndIf ;Encrypt data $xEncryptedText = __CryptoNG_BCryptEncrypt_RSA($CNG_BCRYPT_RSA_ALGORITHM, $sText, $hEncryptionKey, $iPadding) If @error Then If $hAlgorithmProvider <> -1 Then __CryptoNG_BcryptCloseAlgorithmProvider($hAlgorithmProvider) If $hEncryptionKey <> -1 Then __CryptoNG_BcryptDestroyKey($hEncryptionKey) Return SetError(4, 0, "") EndIf ;Clean up If $hAlgorithmProvider <> -1 Then __CryptoNG_BcryptCloseAlgorithmProvider($hAlgorithmProvider) If $hEncryptionKey <> -1 Then __CryptoNG_BcryptDestroyKey($hEncryptionKey) Return $xEncryptedText EndFunc Read Public or Pravite key information data tool (Read PEM) GDI+ Image deskew and crop
argumentum Posted February 27, 2025 Posted February 27, 2025 7 hours ago, konya said: ...hoping to be helpful to you. As is, it is not. You could take all you posted here and put it in the examples section, and in the place of this post, a link to the examples area post. Also add a link in the code for users to find the includes #include <bignum.au3> ; https://get it from here and add comments for the reader of the post, to have context as otherwise, ...what is this and what does it solve. Thanks TheXman 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
dgood71 Posted Thursday at 02:04 AM Posted Thursday at 02:04 AM In doing some experimenting with this I found a bit of a bug in _CryptoNG_CryptBinaryToString in that there's a crash if the binary size goes over about 65536 bytes. Here's code that demonstrates this limit. Output from the script show this: CryptoNG 2.4.0 | AutoIt 3.3.18.0 x86 | WIN_11 build 22631 Encoding 10000 bytes (expect 13336 Base64 chars)... ok, got 13336 chars Encoding 30000 bytes (expect 40000 Base64 chars)... ok, got 40000 chars Encoding 45000 bytes (expect 60000 Base64 chars)... ok, got 60000 chars Encoding 48000 bytes (expect 64000 Base64 chars)... ok, got 64000 chars Encoding 49000 bytes (expect 65336 Base64 chars)... ok, got 65336 chars Encoding 49152 bytes (expect 65536 Base64 chars)... ok, got 65536 chars Encoding 50000 bytes (expect 66668 Base64 chars)... !>21:39:38 AutoIt3.exe ended.rc:-1073741819 +>21:39:38 AutoIt3Wrapper Finished. expandcollapse popup;================================================================================================================================ ; CryptoNG_B64_CrashDemo.au3 ; ; Demonstrates a hard process crash (access violation, no @error possible) in ; _CryptoNG_CryptBinaryToString when the binary input is larger than ~49 KB. ; ; Observed with: CryptoNG 2.4.0, AutoIt 3.3.18.0 (x86), Windows 11 build 22631 ; ; Each attempt is announced on the console BEFORE the call is made, so when ; the process dies, the last line printed identifies the failing size. ; ; Expected Base64 length for n bytes = ceil(n/3)*4. The crash begins right ; around the size where that figure exceeds 65,535 characters (~49,151 bytes ; of input), which points at AutoIt's documented DllCall "str"/"wstr" buffer ; limit of 65,536 characters. ;================================================================================================================================ #include "CryptoNG.au3" ConsoleWrite("CryptoNG " & $CNG_VERSION & " | AutoIt " & @AutoItVersion & (@AutoItX64 ? " x64" : " x86") & _ " | " & @OSVersion & " build " & @OSBuild & @CRLF & @CRLF) Local $aSizes[8] = [10000, 30000, 45000, 48000, 49000, 49152, 50000, 100000] Local $iFlags = BitOR($CNG_CRYPT_STRING_BASE64, $CNG_CRYPT_STRING_NOCRLF) For $i = 0 To UBound($aSizes) - 1 Local $iBytes = $aSizes[$i] Local $iExpectedChars = Int(($iBytes + 2) / 3) * 4 Local $xData = _CryptoNG_GenerateRandom($CNG_BCRYPT_RNG_ALGORITHM, $iBytes) If @error Then ConsoleWrite("GenerateRandom failed @error=" & @error & @CRLF) ExitLoop EndIf ;Announce BEFORE the call - if the process dies, this is the failing size ConsoleWrite(StringFormat("Encoding %7i bytes (expect %7i Base64 chars)... ", $iBytes, $iExpectedChars)) Local $sBase64 = _CryptoNG_CryptBinaryToString($xData, $iFlags) If @error Then ConsoleWrite("returned @error=" & @error & " @extended=" & @extended & @CRLF) Else ConsoleWrite("ok, got " & StringLen($sBase64) & " chars" & @CRLF) EndIf Next ConsoleWrite(@CRLF & "Script completed without crashing." & @CRLF) Here are AI generated versions (Claude/Fable 5) that don't exhibit the same issue: expandcollapse popupFunc __AesGcm_CryptBinaryToString($xData, $iStringFormat) Local $aRet ;Validate parameters If Not IsBinary($xData) Then Return SetError(-1, 0, "") Local $iDataLen = BinaryLen($xData) ;Copy binary into a struct buffer Local $tData = DllStructCreate("byte data[" & $iDataLen & "]") DllStructSetData($tData, "data", $xData) ;Call 1 - query required output size (in WCHARs, includes null terminator) $aRet = DllCall("crypt32.dll", "bool", "CryptBinaryToStringW", _ "struct*", $tData, "dword", $iDataLen, "dword", $iStringFormat, _ "ptr", 0, "dword*", 0) If @error Then Return SetError(1, @error, "") If Not $aRet[0] Then Return SetError(2, 0, "") Local $iChars = $aRet[5] ;Call 2 - convert into a struct-backed output buffer (no wstr size limit) Local $tOut = DllStructCreate("wchar text[" & $iChars & "]") $aRet = DllCall("crypt32.dll", "bool", "CryptBinaryToStringW", _ "struct*", $tData, "dword", $iDataLen, "dword", $iStringFormat, _ "struct*", $tOut, "dword*", $iChars) If @error Then Return SetError(1, @error, "") If Not $aRet[0] Then Return SetError(2, 0, "") Return DllStructGetData($tOut, "text") EndFunc ;==>__AesGcm_CryptBinaryToString ;================================================================= Func __AesGcm_CryptStringToBinary($sData, $iStringFormat) Local $aRet ;Validate parameters If Not IsString($sData) Or $sData = "" Then Return SetError(-1, 0, "") Local $iChars = StringLen($sData) ;Copy the string into a struct buffer (avoids the wstr input limit too) Local $tIn = DllStructCreate("wchar text[" & ($iChars + 1) & "]") DllStructSetData($tIn, "text", $sData) ;Call 1 - query required output size (also validates the input format) $aRet = DllCall("crypt32.dll", "bool", "CryptStringToBinaryW", _ "struct*", $tIn, "dword", $iChars, "dword", $iStringFormat, _ "ptr", 0, "dword*", 0, "ptr", 0, "ptr", 0) If @error Then Return SetError(1, @error, "") If Not $aRet[0] Then Return SetError(2, 0, "") Local $iBytes = $aRet[5] ;Call 2 - convert into a struct-backed output buffer Local $tOut = DllStructCreate("byte data[" & $iBytes & "]") $aRet = DllCall("crypt32.dll", "bool", "CryptStringToBinaryW", _ "struct*", $tIn, "dword", $iChars, "dword", $iStringFormat, _ "struct*", $tOut, "dword*", $iBytes, "ptr", 0, "ptr", 0) If @error Then Return SetError(1, @error, "") If Not $aRet[0] Then Return SetError(2, 0, "") ;$aRet[5] (the 5th parameter, the dword* byte count) holds the actual bytes written Return BinaryMid(DllStructGetData($tOut, "data"), 1, $aRet[5]) EndFunc ;==>__AesGcm_CryptStringToBinary
dgood71 Posted Thursday at 06:40 PM Posted Thursday at 06:40 PM I decided to dig a little deeper into the CryptoNG 2.4.0 UDF with AI to identify potential issues with the code. I sent the entire CryptoNG.au3 to Claude and asked for a validation. After analyzing the multiple thousands of lines of code, the result was about a half dozen bugs. That's absolutely amazing!! - if *I* was going to write a few thousand lines of code, I guarantee that the bug count would be exponentially higher, and that says a lot about the quality of TheXMan's work. I love this UDF, and I appreciate all the time and extensive effort that's gone into maintaining it all these years. I also want to do what I can to help improve things when possible. As such, here's a list of the issues that were identified by AI. I've looked at them and they appear to me to be legit, however it's always good for more eyes to take a look. 1. Wrong conversion in __CryptoNG_BCryptHashData (line 6027) — affects hash correctness. Function __CryptoNG_BCryptHashData ;Create a data buffer and move hash data to it If IsString($vData) Then ; Original: $xData = BinaryToString($vData, $SB_UTF8) ; Patched: $xData = StringToBinary($vData, $SB_UTF8) Else $xData = Binary($vData) EndIf 2. _CryptoNG_EnumKeyStorageProvider () returns N copies of the first provider (line 2902) Const $NCRYPT_KSP_NAME_SIZE = DllStructGetSize($tagNCRYPT_KSP_NAME) Corrected: Const $NCRYPT_KSP_NAME_SIZE = DllStructGetSize(DllStructCreate($tagNCRYPT_KSP_NAME)) DllStructGetSize is being given the tag string, not a struct, so it fails and returns 0. The loop then steps through the struct array with a stride of 0 and every iteration reads the same first entry. 3. "Provider" is silently ignored in 10 public functions.∗∗ These accept and document a Provider parameter but never pass it to __CryptoNG_BCryptOpenEncryptionAlgorithmProvider, so they always use the Microsoft Primitive Provider: _CryptoNG_3DES_CBC_DecryptData _CryptoNG_AES_CBC_DecryptData _CryptoNG_AES_ECB_DecryptData _CryptoNG_AES_GCM_DecryptData _CryptoNG_DecryptData _CryptoNG_ECDSA_SignHash _CryptoNG_ECDSA_VerifySignature _CryptoNG_RSA_DecryptData _CryptoNG_RSA_SignHash _CryptoNG_RSA_VerifySignature Notice the asymmetry: the *Encrypt* variants pass it, the *Decrypt/Sign/Verify* variants mostly don't. Harmless with the default provider, but if you ever specify one, encrypt and decrypt could run on different providers without any error. 4. Resource leaks + wrong return type in the IV/nonce validation paths.** In the four `*_CBC_*File` functions, the IV length check happens *after* the input/output files are opened and the key handle is generated, but the failure path only closes the algorithm provider, so the two file handles and the key handle leak. The output file is also left created-but-empty on disk. On top of that, these paths Return SetError(8, 0, "") when every other failure in those functions returns False, so a caller testing "If Not result" gets inconsistent behavior( and False both test falsy, but result = False comparisons and the documented contract break). The same key-handle leak exists in _CryptoNG_3DES_CBC_DecryptData / _CryptoNG_AES_CBC_DecryptData (IV checked after key generation) and in both AES-GCM functions (nonce/auth-tag checked after key generation. Simplest fix is to move the IV/nonce validation up before any handles are opened — it doesn't depend on them. 5. Dead constant-vs-constant comparisons. Lines 601, 832, 1063, 1310: If $CNG_BCRYPT_3DES_ALGORITHM <> $CNG_BCRYPT_RC4_ALGORITHM Then (and the AES equivalent) compare two literals — always true. Harmless, but not necessary. 6. Minor items: __CryptoNG_BCryptCreateHash closes the algorithm provider on a DllCall failure, but every caller also closes it in their error path → double close of the same handle. In _CryptoNG_ECDSA_CreateKeyPair / _CryptoNG_RSA_CreateKeyPair(Ex), the FileWrite failure paths return without FileClose($hFile). __CryptoNG_IsAuthTagByteLengthValid does Mod($iAuthTagBytes, dwIncrement) without the dwIncrement <> 0 guard that its sibling __CryptoNG_IsKeyBitLengthValid has — divide-by-zero if a provider ever reports increment 0. _CryptoNG_CryptBinaryToString uses a "wstr" return buffer, which AutoIt caps at 65,535 characters; converting more than roughly 48 KB of binary to Base64 will truncate. If you ever feed it large blobs, switch the output to a wchar struct sized from the first call. It also returns False on DllCall error where the docs promise "". __CryptoNG_BCryptSetProperty's string case passes BinaryLen($vValue) as cbInput — that's the ANSI byte count while the data is marshaled as wstr (UTF-16). It happens to work for chaining-mode strings because Windows only reads up to the declared length and the values are ASCII, but (StringLen($vValue) + 1) * 2 would be the correct size. I also had AI generate a test script to verify CryptoNG output against known good test parameters; that code is below. expandcollapse popup;================================================================================================================================ ; CryptoNG_BugDemo.au3 - Known-answer test bed demonstrating bugs in CryptoNG v2.4.0 ; ; ; Reference values come from published standards: ; T1 FIPS 180-2 SHA-256("abc") ; T2 RFC 4231 Test Case 2 HMAC-SHA256(key="Jefe", "what do ya want for nothing?") ; T3 RFC 6070 PBKDF2-HMAC-SHA1("password", "salt", c=4096, dkLen=20) ; T4 NIST SP 800-38A F.2.5 AES-256-CBC, first block ; T5 SHA-256 of the UTF-8 bytes of "caf<e-acute>" (verify yourself: printf 'caf\xc3\xa9' | sha256sum) ;================================================================================================================================ #include "CryptoNG.au3" Global $g_iPass = 0, $g_iFail = 0 ConsoleWrite(@CRLF & "CryptoNG bug demo - UDF version " & _CryptoNG_Version() & @CRLF & @CRLF) ;-------------------------------------------------------------------------------------------------------------------- ; T1-T4: CONTROLS. These use ASCII-only input and exercise code paths that are correct in v2.4.0. ;-------------------------------------------------------------------------------------------------------------------- ; T1 - FIPS 180-2: SHA-256("abc") Local $xHash = _CryptoNG_HashData($CNG_BCRYPT_SHA256_ALGORITHM, "abc") Report("T1 CONTROL SHA-256('abc') [FIPS 180-2]", _ HexOf($xHash), "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad") ; T2 - RFC 4231 Test Case 2: HMAC-SHA256, key "Jefe" $xHash = _CryptoNG_HashData($CNG_BCRYPT_SHA256_ALGORITHM, "what do ya want for nothing?", True, "Jefe") Report("T2 CONTROL HMAC-SHA256 [RFC 4231 TC2]", _ HexOf($xHash), "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843") ; T3 - RFC 6070: PBKDF2-HMAC-SHA1("password", "salt", 4096 iterations, 20 bytes) Local $xKey = _CryptoNG_PBKDF2("password", "salt", 4096, 160) ; 160 bits = 20 bytes, default hash = SHA1 Report("T3 CONTROL PBKDF2-HMAC-SHA1 c=4096 [RFC 6070]", _ HexOf($xKey), "4b007901b765489abead49d926f721d065a429c1") ; T4 - NIST SP 800-38A F.2.5: AES-256-CBC, first ciphertext block Local $xAesKey = Binary("0x603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4") Local $xAesIV = Binary("0x000102030405060708090A0B0C0D0E0F") Local $xAesPT = Binary("0x6BC1BEE22E409F96E93D7E117393172A") Local $xCipher = _CryptoNG_AES_CBC_EncryptData($xAesPT, $xAesKey, $xAesIV) Report("T4 CONTROL AES-256-CBC block 1 [NIST SP 800-38A F.2.5]", _ HexOf(BinaryMid($xCipher, 1, 16)), "f58c4c04d6e5f1ba779eabfb5f7bfbd6") ;-------------------------------------------------------------------------------------------------------------------- ; T5: BUG #1 - __CryptoNG_BCryptHashData uses BinaryToString() instead of StringToBinary(). ; Any string containing non-ASCII characters is hashed as ANSI bytes (or mangled), not UTF-8. ; "caf" & ChrW(233) is "caf<e-acute>"; its UTF-8 bytes are 63 61 66 C3 A9. ; Verify the expected digest yourself on any Linux box: printf 'caf\xc3\xa9' | sha256sum ;-------------------------------------------------------------------------------------------------------------------- Local $sCafe = "caf" & ChrW(233) $xHash = _CryptoNG_HashData($CNG_BCRYPT_SHA256_ALGORITHM, $sCafe) Report("T5 BUG#1 SHA-256 of UTF-8 'caf" & ChrW(233) & "'", _ HexOf($xHash), "850f7dc43910ff890f8879c0ed26fe697c93a067ad93a7d50f466a7028a9bf4e") If HexOf($xHash) = "dafd66c0b98965e688be1fc12942c09f0350e6be0685017c3f234e97d0adc92e" Then _ ConsoleWrite(" (actual value matches the ANSI/cp1252 digest - data was hashed as ANSI, not UTF-8)" & @CRLF) ;-------------------------------------------------------------------------------------------------------------------- ; T6: BUG #1 cross-check needing NO external reference value: hashing the string directly must match ; hashing a UTF-8 file with the same content. (HashFile reads raw bytes, so it is unaffected by the bug.) ;-------------------------------------------------------------------------------------------------------------------- Local $sUtf8File = @TempDir & "\cng_demo_utf8.txt" Local $hF = FileOpen($sUtf8File, $FO_OVERWRITE + 256) ; 256 = $FO_UTF8_NOBOM FileWrite($hF, $sCafe) FileClose($hF) Local $xFileHash = _CryptoNG_HashFile($CNG_BCRYPT_SHA256_ALGORITHM, $sUtf8File) Report("T6 BUG#1 HashData(string) = HashFile(same content, UTF-8 file)", HexOf($xHash), HexOf($xFileHash)) FileDelete($sUtf8File) ;-------------------------------------------------------------------------------------------------------------------- ; T7: BUG #3 - $sProvider is silently ignored by the Decrypt/Sign/Verify functions. ; Decrypting with a provider name that does not exist MUST fail; in v2.4.0 it "succeeds". ;-------------------------------------------------------------------------------------------------------------------- Local $sBogus = "Bogus Provider That Does Not Exist" $xCipher = _CryptoNG_AES_CBC_EncryptData("provider test", $xAesKey, $xAesIV) _CryptoNG_AES_CBC_EncryptData("provider test", $xAesKey, $xAesIV, $sBogus) Report("T7a CONTROL Encrypt with bogus provider is rejected", (@error <> 0), True) _CryptoNG_AES_CBC_DecryptData($xCipher, $xAesKey, $xAesIV, $sBogus) Report("T7b BUG#3 Decrypt with bogus provider is rejected", (@error <> 0), True) ;-------------------------------------------------------------------------------------------------------------------- ; T8: BUG #2 - _CryptoNG_EnumKeyStorageProviders steps through the result array with a stride of 0 ; and returns N copies of the FIRST provider. A normal Windows box registers at least ; "Microsoft Software Key Storage Provider", "...Smart Card...", and "...Platform Crypto Provider". ;-------------------------------------------------------------------------------------------------------------------- Local $aKSP = _CryptoNG_EnumKeyStorageProviders() If @error Or Not IsArray($aKSP) Then Report("T8 BUG#2 EnumKeyStorageProviders returns distinct entries", "call failed: " & _CryptoNG_LastErrorMessage(), "an array") ElseIf UBound($aKSP) < 2 Then ConsoleWrite("T8 SKIPPED only " & UBound($aKSP) & " key storage provider registered; cannot detect the stride bug" & @CRLF) Else Local $bAllSame = True For $i = 1 To UBound($aKSP) - 1 If $aKSP[$i] <> $aKSP[0] Then $bAllSame = False Next Report("T8 BUG#2 EnumKeyStorageProviders returns distinct entries (got " & UBound($aKSP) & ")", Not $bAllSame, True) For $i = 0 To UBound($aKSP) - 1 ConsoleWrite(" [" & $i & "] " & $aKSP[$i] & @CRLF) Next EndIf ;-------------------------------------------------------------------------------------------------------------------- ; T9: BUG #4 - the bad-IV failure path in the CBC *File functions returns "" instead of the documented ; False, and leaks both file handles (so the files cannot be deleted afterwards) and the key handle. ;-------------------------------------------------------------------------------------------------------------------- Local $sPlainFile = @TempDir & "\cng_demo_plain.txt" Local $sEncFile = @TempDir & "\cng_demo_enc.bin" Local $sDecFile = @TempDir & "\cng_demo_dec.txt" $hF = FileOpen($sPlainFile, $FO_OVERWRITE) FileWrite($hF, "file handle leak test") FileClose($hF) _CryptoNG_AES_CBC_EncryptFile($sPlainFile, $sEncFile, $xAesKey, $xAesIV) Local $vRet = _CryptoNG_AES_CBC_DecryptFile($sEncFile, $sDecFile, $xAesKey, Binary("0x00")) ; 1-byte IV -> must fail Local $iErr = @error Report("T9a Bad-IV decrypt sets @error = 8", $iErr, 8) Report("T9b BUG#4 Bad-IV decrypt returns Bool False per docs (got type " & VarGetType($vRet) & ")", _ (VarGetType($vRet) = "Bool" And $vRet = False), True) Report("T9c BUG#4 Output file deletable afterwards (no leaked handle)", (FileDelete($sDecFile) = 1), True) Report("T9d BUG#4 Input file deletable afterwards (no leaked handle)", (FileDelete($sEncFile) = 1), True) FileDelete($sPlainFile) ;-------------------------------------------------------------------------------------------------------------------- ConsoleWrite(@CRLF & StringFormat("RESULT: %i passed, %i failed", $g_iPass, $g_iFail) & @CRLF) ConsoleWrite("Expected against ORIGINAL v2.4.0: T1-T4 and T7a pass; T5, T6, T7b, T8, T9b, T9c, T9d FAIL." & @CRLF) ConsoleWrite("Expected against PATCHED copy: everything passes." & @CRLF) ;=== helpers ==================================================================================================================== Func HexOf($xBin) Return StringLower(StringTrimLeft(String(Binary($xBin)), 2)) EndFunc Func Report($sTest, $vActual, $vExpected) Local $bPass = ($vActual == $vExpected) If IsBool($vExpected) Then $bPass = ($vActual = $vExpected) If $bPass Then $g_iPass += 1 ConsoleWrite("PASS " & $sTest & @CRLF) Else $g_iFail += 1 ConsoleWrite("FAIL " & $sTest & @CRLF) ConsoleWrite(" expected: " & String($vExpected) & @CRLF) ConsoleWrite(" actual : " & String($vActual) & @CRLF) EndIf EndFunc I hope this input helps to make a great UDF even better. With today's technology it's much easier to identify issues than it was even a year or so ago. I appreciate how much time and effort was required to create this UDF years ago and maintain it even now, and my post is by no means intended to make light of the tremendous amount of work that's gone into this code. Times and tools are changing, and my hope is that we can keep quality code moving forward with modern tools while remembering that the hard work, done by actual people, is how we got to where we are today. Note to TheXman: I have a patched version of the 2.4.0 UDF that passes all the tests in the demo code posted here, and I'd be happy to send it to you for review if you want it. I won't post the entire code here as I believe revisions should be handled through "official" channels. Thank you for all your effort in this awesome work.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now