From f5f65ab030307ab90a03f3923d4bfe8b9e5e9de7 Mon Sep 17 00:00:00 2001 From: Andreas Bail Date: Thu, 20 Aug 2026 15:54:24 +0200 Subject: [PATCH] yeet tests and libcrypt --- .gitignore | 1 - libcrypt/libcrypt.ahk | 932 +++++++++++++++++++++++ libcrypt/libcrypt_v2.ahk2 | 1062 ++++++++++++++++++++++++++ libcrypt/testALTlibcrypt.ahk2 | 1305 ++++++++++++++++++++++++++++++++ libcrypt/test_libcrypt_v2.ahk2 | 28 + test.ahk2 | 22 + 6 files changed, 3349 insertions(+), 1 deletion(-) create mode 100644 libcrypt/libcrypt.ahk create mode 100644 libcrypt/libcrypt_v2.ahk2 create mode 100644 libcrypt/testALTlibcrypt.ahk2 create mode 100644 libcrypt/test_libcrypt_v2.ahk2 create mode 100644 test.ahk2 diff --git a/.gitignore b/.gitignore index 7aff20e..b883f1f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ *.exe -test* \ No newline at end of file diff --git a/libcrypt/libcrypt.ahk b/libcrypt/libcrypt.ahk new file mode 100644 index 0000000..247edd0 --- /dev/null +++ b/libcrypt/libcrypt.ahk @@ -0,0 +1,932 @@ +LC_Version := "0.0.21.01" + +LC_ASCII2Bin(s,pretty:=0) { + r:="" + Loop, % l:=StrLen(s) + { + z:=Asc(SubStr(s,A_Index,1)),y:="",p:=1 + Loop, 8 + b:=!!(z&p),y:=b y,p:=p<<1 + r.=y + if (pretty && (A_Index>(8-A_Index) & 1 + if Pretty ; Perhaps a regex at the end instead of a check in every loop would be better + Out .= " " + } + ; Out := RegExReplace(Out, "(\d{8})", "$1 ") ; For example, this +} + +LC_BinStr_Decode(ByRef Out, ByRef In) { + ByteCount := StrLen(In)/8 + VarSetCapacity(Out, ByteCount, 0) + BitIndex := 1 + Loop, % ByteCount + { + Byte := 0 + Loop, 8 + Byte := Byte<<1 | SubStr(In, BitIndex++, 1) + NumPut(Byte, Out, A_Index-1, "UChar") + } +} + + +LC_Base64_EncodeText(Text,Encoding="UTF-8") +{ + VarSetCapacity(Bin, StrPut(Text, Encoding)) + LC_Base64_Encode(Base64, Bin, StrPut(Text, &Bin, Encoding)-1) + return Base64 +} + +LC_Base64_DecodeText(Text,Encoding="UTF-8") +{ + Len := LC_Base64_Decode(Bin, Text) + return StrGet(&Bin, Len, Encoding) +} + +LC_Base64_Encode(ByRef Out, ByRef In, InLen) +{ + return LC_Bin2Str(Out, In, InLen, 0x40000001) +} + +LC_Base64_Decode(ByRef Out, ByRef In) +{ + return LC_Str2Bin(Out, In, 0x1) +} + + +LC_Bin2Hex(ByRef Out, ByRef In, InLen, Pretty=False) +{ + return LC_Bin2Str(Out, In, InLen, Pretty ? 0xb : 0x4000000c) +} + +LC_Hex2Bin(ByRef Out, ByRef In) +{ + return LC_Str2Bin(Out, In, 0x8) +} + +LC_Bin2Str(ByRef Out, ByRef In, InLen, Flags) +{ + DllCall("Crypt32.dll\CryptBinaryToString", "Ptr", &In + , "UInt", InLen, "UInt", Flags, "Ptr", 0, "UInt*", OutLen) + VarSetCapacity(Out, OutLen * (1+A_IsUnicode)) + DllCall("Crypt32.dll\CryptBinaryToString", "Ptr", &In + , "UInt", InLen, "UInt", Flags, "Str", Out, "UInt*", OutLen) + return OutLen +} + +LC_Str2Bin(ByRef Out, ByRef In, Flags) +{ + DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &In, "UInt", StrLen(In) + , "UInt", Flags, "Ptr", 0, "UInt*", OutLen, "Ptr", 0, "Ptr", 0) + VarSetCapacity(Out, OutLen) + DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &In, "UInt", StrLen(In) + , "UInt", Flags, "Str", Out, "UInt*", OutLen, "Ptr", 0, "Ptr", 0) + return OutLen +} + +; +; Version: 2014.03.06-1518, jNizM +; see https://en.wikipedia.org/wiki/Caesar_cipher +; =================================================================================== + +LC_Caesar(string, num := 2) { + ret := c := "" + loop, parse, string + { + c := Asc(A_LoopField) + if (c > 64) && (c < 91) + ret .= Chr(Mod(c - 65 + num, 26) + 65) + else if (c > 96) && (c < 123) + ret .= Chr(Mod(c - 97 + num, 26) + 97) + else + ret .= A_LoopField + } + return ret +} + +LC_CalcAddrHash(addr, length, algid, byref hash = 0, byref hashlength = 0) { + static h := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"] + static b := h.minIndex() + hProv := hHash := o := "" + if (DllCall("advapi32\CryptAcquireContext", "Ptr*", hProv, "Ptr", 0, "Ptr", 0, "UInt", 24, "UInt", 0xf0000000)) + { + if (DllCall("advapi32\CryptCreateHash", "Ptr", hProv, "UInt", algid, "UInt", 0, "UInt", 0, "Ptr*", hHash)) + { + if (DllCall("advapi32\CryptHashData", "Ptr", hHash, "Ptr", addr, "UInt", length, "UInt", 0)) + { + if (DllCall("advapi32\CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", 0, "UInt*", hashlength, "UInt", 0)) + { + VarSetCapacity(hash, hashlength, 0) + if (DllCall("advapi32\CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", &hash, "UInt*", hashlength, "UInt", 0)) + { + loop % hashlength + { + v := NumGet(hash, A_Index - 1, "UChar") + o .= h[(v >> 4) + b] h[(v & 0xf) + b] + } + } + } + } + DllCall("advapi32\CryptDestroyHash", "Ptr", hHash) + } + DllCall("advapi32\CryptReleaseContext", "Ptr", hProv, "UInt", 0) + } + return o +} +LC_CalcStringHash(string, algid, encoding = "UTF-8", byref hash = 0, byref hashlength = 0) { + chrlength := (encoding = "CP1200" || encoding = "UTF-16") ? 2 : 1 + length := (StrPut(string, encoding) - 1) * chrlength + VarSetCapacity(data, length, 0) + StrPut(string, &data, floor(length / chrlength), encoding) + return LC_CalcAddrHash(&data, length, algid, hash, hashlength) +} +LC_CalcHexHash(hexstring, algid) { + length := StrLen(hexstring) // 2 + VarSetCapacity(data, length, 0) + loop % length + { + NumPut("0x" SubStr(hexstring, 2 * A_Index - 1, 2), data, A_Index - 1, "Char") + } + return LC_CalcAddrHash(&data, length, algid) +} +LC_CalcFileHash(filename, algid, continue = 0, byref hash = 0, byref hashlength = 0) { + fpos := "" + if (!(f := FileOpen(filename, "r"))) + { + return + } + f.pos := 0 + if (!continue && f.length > 0x7fffffff) + { + return + } + if (!continue) + { + VarSetCapacity(data, f.length, 0) + f.rawRead(&data, f.length) + f.pos := oldpos + return LC_CalcAddrHash(&data, f.length, algid, hash, hashlength) + } + hashlength := 0 + while (f.pos < f.length) + { + readlength := (f.length - fpos > continue) ? continue : f.length - f.pos + VarSetCapacity(data, hashlength + readlength, 0) + DllCall("RtlMoveMemory", "Ptr", &data, "Ptr", &hash, "Ptr", hashlength) + f.rawRead(&data + hashlength, readlength) + h := LC_CalcAddrHash(&data, hashlength + readlength, algid, hash, hashlength) + } + return h +} + +LC_CRC32(string, encoding = "UTF-8") { + chrlength := (encoding = "CP1200" || encoding = "UTF-16") ? 2 : 1 + length := (StrPut(string, encoding) - 1) * chrlength + VarSetCapacity(data, length, 0) + StrPut(string, &data, floor(length / chrlength), encoding) + hMod := DllCall("Kernel32.dll\LoadLibrary", "Str", "Ntdll.dll") + SetFormat, Integer, % SubStr((A_FI := A_FormatInteger) "H", 0) + CRC32 := DllCall("Ntdll.dll\RtlComputeCrc32", "UInt", 0, "UInt", &data, "UInt", length, "UInt") + CRC := SubStr(CRC32 | 0x1000000000, -7) + DllCall("User32.dll\CharLower", "Str", CRC) + SetFormat, Integer, %A_FI% + return CRC, DllCall("Kernel32.dll\FreeLibrary", "Ptr", hMod) +} +LC_HexCRC32(hexstring) { + length := StrLen(hexstring) // 2 + VarSetCapacity(data, length, 0) + loop % length + { + NumPut("0x" SubStr(hexstring, 2 * A_Index -1, 2), data, A_Index - 1, "Char") + } + hMod := DllCall("Kernel32.dll\LoadLibrary", "Str", "Ntdll.dll") + SetFormat, Integer, % SubStr((A_FI := A_FormatInteger) "H", 0) + CRC32 := DllCall("Ntdll.dll\RtlComputeCrc32", "UInt", 0, "UInt", &data, "UInt", length, "UInt") + CRC := SubStr(CRC32 | 0x1000000000, -7) + DllCall("User32.dll\CharLower", "Str", CRC) + SetFormat, Integer, %A_FI% + return CRC, DllCall("Kernel32.dll\FreeLibrary", "Ptr", hMod) +} +LC_FileCRC32(sFile := "", cSz := 4) { + Bytes := "" + cSz := (cSz < 0 || cSz > 8) ? 2**22 : 2**(18 + cSz) + VarSetCapacity(Buffer, cSz, 0) + hFil := DllCall("Kernel32.dll\CreateFile", "Str", sFile, "UInt", 0x80000000, "UInt", 3, "Int", 0, "UInt", 3, "UInt", 0, "Int", 0, "UInt") + if (hFil < 1) + { + return hFil + } + hMod := DllCall("Kernel32.dll\LoadLibrary", "Str", "Ntdll.dll") + CRC32 := 0 + DllCall("Kernel32.dll\GetFileSizeEx", "UInt", hFil, "Int64", &Buffer), fSz := NumGet(Buffer, 0, "Int64") + loop % (fSz // cSz + !!Mod(fSz, cSz)) + { + DllCall("Kernel32.dll\ReadFile", "UInt", hFil, "Ptr", &Buffer, "UInt", cSz, "UInt*", Bytes, "UInt", 0) + CRC32 := DllCall("Ntdll.dll\RtlComputeCrc32", "UInt", CRC32, "UInt", &Buffer, "UInt", Bytes, "UInt") + } + DllCall("Kernel32.dll\CloseHandle", "Ptr", hFil) + SetFormat, Integer, % SubStr((A_FI := A_FormatInteger) "H", 0) + CRC32 := SubStr(CRC32 + 0x1000000000, -7) + DllCall("User32.dll\CharLower", "Str", CRC32) + SetFormat, Integer, %A_FI% + return CRC32, DllCall("Kernel32.dll\FreeLibrary", "Ptr", hMod) +} + +;from joedf : fork-fusion of jNizM+Laszlo's functions [to_decimal()+ToBase()] +LC_To_Dec(b, n) { ; 1 < b <= 36, n >= 0 + d:=0 + StringUpper,n,n + loop % StrLen(n) + { + d *= b, k:=SubStr(n,A_Index,1) + if k is not Integer + k:=Asc(k)-55 + d += k + } + return d +} +;from Laszlo : http://www.autohotkey.com/board/topic/15951-base-10-to-base-36-conversion/#entry103624 +LC_From_Dec(b,n) { ; 1 < b <= 36, n >= 0 + Loop { + d := mod(n,b), n //= b + m := (d < 10 ? d : Chr(d+55)) . m + IfLess n,1, Break + } + Return m +} +LC_Dec2Hex(x) { + return LC_From_Dec(16,x) +} +LC_Hex2Dec(x) { + return LC_To_Dec(16,x) +} +LC_Numvert(num,from,to) { ; from joedf : http://ahkscript.org/boards/viewtopic.php?f=6&t=6363 + return LC_From_Dec(to,LC_To_Dec(from,num)) +} + +; +; Date Updated: +; Friday, November 23rd, 2012 - Tuesday, February 10th, 2015 +; +; Script Function: +; Function Library to Encrypt / Decrypt in Div2 (by Joe DF) +; Div2 was invented with a friend for fun, back in ~2010. +; The string is "divided" in 2 during encryption. It is a +; simple reordering of the characters in a string. The was +; to have a human-readable/decryptable message. +; +; Notes: +; AutoTrim should turned off, for the encryption to work properly +; because, in Div2, and count as a character. +; + +LC_Div2_encode(input, WithAutoTrim:=1, numproc:=1) { + if (WithAutoTrim) + StringReplace,input,input,%A_Space%,_,A + loop, %numproc% + { + final:="", inputlen := StrLen(input) + divmax := ceil((0.5 * inputlen) + 1) + loop, %inputlen% + { + temp := SubStr(input,A_Index,1) + q := inputlen + 1 - A_Index + temp2 := SubStr(input,q,1) + if (A_Index < divmax) { + final .= temp + if (A_Index != q) + final .= temp2 + } + if (A_Index >= divmax) + Break + } + input := final + } + return final +} + +LC_Div2_decode(input, WithAutoTrim:=1, numproc:=1) { + if (WithAutoTrim) + StringReplace,input,input,%A_Space%,_,A + loop, %numproc% + { + i := 1, final:="", inputlen := StrLen(input) + loop, % loopc := ceil(inputlen * (1/2)) + { + if (i <= inputlen) + final .= SubStr(input,i,1) + i += 2 + } + i := inputlen + loop, %loopc% + { + if (i <= inputlen) { + if (mod(SubStr(i,0,1)+0,2)==1) { + if (i != 1) + final .= SubStr(input,i-1,1) + } else { + final .= SubStr(input,i,1) + } + } + i -= 2 + } + input := final + } + return final +} + + +LC_HMAC(Key, Message, Algo := "MD5") { + static Algorithms := {MD2: {ID: 0x8001, Size: 64} + , MD4: {ID: 0x8002, Size: 64} + , MD5: {ID: 0x8003, Size: 64} + , SHA: {ID: 0x8004, Size: 64} + , SHA256: {ID: 0x800C, Size: 64} + , SHA384: {ID: 0x800D, Size: 128} + , SHA512: {ID: 0x800E, Size: 128}} + static iconst := 0x36 + static oconst := 0x5C + if (!(Algorithms.HasKey(Algo))) + { + return "" + } + Hash := KeyHashLen := InnerHashLen := "" + HashLen := 0 + AlgID := Algorithms[Algo].ID + BlockSize := Algorithms[Algo].Size + MsgLen := StrPut(Message, "UTF-8") - 1 + KeyLen := StrPut(Key, "UTF-8") - 1 + VarSetCapacity(K, KeyLen + 1, 0) + StrPut(Key, &K, KeyLen, "UTF-8") + if (KeyLen > BlockSize) + { + LC_CalcAddrHash(&K, KeyLen, AlgID, KeyHash, KeyHashLen) + } + + VarSetCapacity(ipad, BlockSize + MsgLen, iconst) + Addr := KeyLen > BlockSize ? &KeyHash : &K + Length := KeyLen > BlockSize ? KeyHashLen : KeyLen + i := 0 + while (i < Length) + { + NumPut(NumGet(Addr + 0, i, "UChar") ^ iconst, ipad, i, "UChar") + i++ + } + if (MsgLen) + { + StrPut(Message, &ipad + BlockSize, MsgLen, "UTF-8") + } + LC_CalcAddrHash(&ipad, BlockSize + MsgLen, AlgID, InnerHash, InnerHashLen) + + VarSetCapacity(opad, BlockSize + InnerHashLen, oconst) + Addr := KeyLen > BlockSize ? &KeyHash : &K + Length := KeyLen > BlockSize ? KeyHashLen : KeyLen + i := 0 + while (i < Length) + { + NumPut(NumGet(Addr + 0, i, "UChar") ^ oconst, opad, i, "UChar") + i++ + } + Addr := &opad + BlockSize + i := 0 + while (i < InnerHashLen) + { + NumPut(NumGet(InnerHash, i, "UChar"), Addr + i, 0, "UChar") + i++ + } + return LC_CalcAddrHash(&opad, BlockSize + InnerHashLen, AlgID) +} + +LC_MD2(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x8001, encoding) +} +LC_HexMD2(hexstring) { + return LC_CalcHexHash(hexstring, 0x8001) +} +LC_FileMD2(filename) { + return LC_CalcFileHash(filename, 0x8001, 64 * 1024) +} +LC_AddrMD2(addr, length) { + return LC_CalcAddrHash(addr, length, 0x8001) +} + +LC_MD4(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x8002, encoding) +} +LC_HexMD4(hexstring) { + return LC_CalcHexHash(hexstring, 0x8002) +} +LC_FileMD4(filename) { + return LC_CalcFileHash(filename, 0x8002, 64 * 1024) +} +LC_AddrMD4(addr, length) { + return LC_CalcAddrHash(addr, length, 0x8002) +} + +LC_MD5(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x8003, encoding) +} +LC_HexMD5(hexstring) { + return LC_CalcHexHash(hexstring, 0x8003) +} +LC_FileMD5(filename) { + return LC_CalcFileHash(filename, 0x8003, 64 * 1024) +} +LC_AddrMD5(addr, length) { + return LC_CalcAddrHash(addr, length, 0x8003) +} + +;nnnik's custom encryption algorithm +;Version 2.1 of the encryption/decryption functions + +LC_nnnik21_encryptStr(str="",pass="") +{ + If !(enclen:=(strput(str,"utf-16")*2)) + return "Error: Nothing to Encrypt" + If !(passlen:=strput(pass,"utf-8")-1) + return "Error: No Pass" + enclen:=Mod(enclen,4) ? (enclen) : (enclen-2) + Varsetcapacity(encbin,enclen,0) + StrPut(str,&encbin,enclen/2,"utf-16") + Varsetcapacity(passbin,passlen+=mod((4-mod(passlen,4)),4),0) + StrPut(pass,&passbin,strlen(pass),"utf-8") + LC_nnnik21_encryptbin(&encbin,enclen,&passbin,passlen) + LC_Base64_Encode(Text, encbin, enclen) + return Text +} + +LC_nnnik21_decryptStr(str="",pass="") +{ + If !((strput(str,"utf-16")*2)) + return "Error: Nothing to Decrypt" + If !((passlen:=strput(pass,"utf-8")-1)) + return "Error: No Pass" + Varsetcapacity(passbin,passlen+=mod((4-mod(passlen,4)),4),0) + StrPut(pass,&passbin,strlen(pass),"utf-8") + enclen:=LC_Base64_Decode(encbin, str) + LC_nnnik21__decryptbin(&encbin,enclen,&passbin,passlen) + return StrGet(&encbin,"utf-16") +} + + +LC_nnnik21_encryptbin(pBin1,sBin1,pBin2,sBin2) +{ + b:=0 + Loop % sBin1/4 + { + a:=numget(pBin1+0,sBin1-A_Index*4,"uint") + numput(a+b,pBin1+0,sBin1-A_Index*4,"uint") + b:=(a+b)*a + } + Loop % sBin2/4 + { + c:=numget(pBin2+0,(A_Index-1)*4,"uint") + b:=0 + Loop % sBin1/4 + { + a:=numget(pBin1+0,(A_Index-1)*4,"uint") + numput((a+b)^c,pBin1+0,(A_Index-1)*4,"uint") + b:=(a+b)*a + } + } +} + +LC_nnnik21__decryptbin(pBin1,sBin1,pBin2,sBin2){ + Loop % sBin2/4 + { + c:=numget(pBin2+0,sBin2-A_Index*4,"uint") + b:=0 + Loop % sBin1/4 + { + a:=numget(pBin1+0,(A_Index-1)*4,"uint") + numput(a:=(a^c)-b,pBin1+0,(A_Index-1)*4,"uint") + b:=(a+b)*a + } + } + b:=0 + Loop % sBin1/4 + { + a:=numget(pBin1+0,sBin1-A_Index*4,"uint") + numput(a:=a-b,pBin1+0,sBin1-A_Index*4,"uint") + b:=(a+b)*a + } +} + + +LC_RC4_Encrypt(Data,Pass) { + Format:=A_FormatInteger,b:=0,j:=0,Key:=Object(),sBox:=Object() + SetFormat,Integer,Hex + VarSetCapacity(Result,StrLen(Data)*2) + Loop 256 + a:=(A_Index-1),Key[a]:=Asc(SubStr(Pass,Mod(a,StrLen(Pass))+1,1)),sBox[a]:=a + Loop 256 + a:=(A_Index-1),b:=(b+sBox[a]+Key[a])&255,sBox[a]:=(sBox[b]+0,sBox[b]:=sBox[a]) ; SWAP(a,b) + Loop Parse, Data + i:=(A_Index&255),j:=(sBox[i]+j)&255,k:=(sBox[i]+sBox[j])&255,sBox[i]:=(sBox[j]+0,sBox[j]:=sBox[i]) ; SWAP(i,j) + ,Result.=SubStr(Asc(A_LoopField)^sBox[k],-1,2) + StringReplace,Result,Result,x,0,All + SetFormat,Integer,%Format% + Return Result +} + +LC_RC4_Decrypt(Data,Pass) { + b:=0,j:=0,x:="0x",Key:=Object(),sBox:=Object() + VarSetCapacity(Result,StrLen(Data)//2) + Loop 256 + a:=(A_Index-1),Key[a]:=Asc(SubStr(Pass,Mod(a,StrLen(Pass))+1,1)),sBox[a]:=a + Loop 256 + a:=(A_Index-1),b:=(b+sBox[a]+Key[a])&255,sBox[a]:=(sBox[b]+0,sBox[b]:=sBox[a]) ; SWAP(a,b) + Loop % StrLen(Data)//2 + i:=(A_Index&255),j:=(sBox[i]+j)&255,k:=(sBox[i]+sBox[j])&255,sBox[i]:=(sBox[j]+0,sBox[j]:=sBox[i]) ; SWAP(i,j) + ,Result.=Chr((x . SubStr(Data,(2*A_Index)-1,2))^sBox[k]) + Return Result +} + +LC_RC4(RC4Data,RC4Pass) { ; Thanks Rajat for original, Updated Libcrypt version + ; http://www.autohotkey.com/board/topic/570-rc4-encryption/page-2#entry25712 + ATrim:=A_AutoTrim,BLines:=A_BatchLines,RC4PassLen:=StrLen(RC4Pass),Key:=Object(),sBox:=Object(),b:=0,RC4Result:="",i:=0,j:=0 + AutoTrim,Off + SetBatchlines,-1 + Loop, 256 + a:=(A_Index-1),ModVal:=Mod(a,RC4PassLen),c:=SubStr(RC4Pass,ModVal+=1,1),Key[a]:=Asc(c),sBox[a]:=a + Loop, 256 + a:=(A_Index-1),b:=Mod(b+sBox[a]+Key[a],256),T:=sBox[a],sBox[a]:=sBox[b],sBox[b]:=T + Loop, Parse, RC4Data + i:=Mod(i+1,256),j:=Mod(sBox[i]+j,256),k:=sBox[Mod(sBox[i]+sBox[j],256)],c:=Asc(A_LoopField)^k,c:=((c==0)?k:c),RC4Result.=Chr(c) + AutoTrim, %ATrim% + SetBatchlines, %BLines% + Return RC4Result +} + +/* + - ROT5 covers the numbers 0-9. + - ROT13 covers the 26 upper and lower case letters of the Latin alphabet (A-Z, a-z). + - ROT18 is a combination of ROT5 and ROT13. + - ROT47 covers all printable ASCII characters, except empty spaces. Besides numbers and the letters of the Latin alphabet, + the following characters are included: + !"#$%&'()*+,-./:;<=>?[\]^_`{|}~ +*/ + +LC_Rot5(string) { + Loop, Parse, string + s .= (strlen((c:=A_LoopField)+0)?((c<5)?c+5:c-5):(c)) + Return s +} + +; by Raccoon July-2009 +; http://rosettacode.org/wiki/Rot-13#AutoHotkey +LC_Rot13(string) { + Loop, Parse, string + { + c := asc(A_LoopField) + if (c >= 97) && (c <= 109) || (c >= 65) && (c <= 77) + c += 13 + else if (c >= 110) && (c <= 122) || (c >= 78) && (c <= 90) + c -= 13 + s .= Chr(c) + } + Return s +} + +LC_Rot18(string) { + return LC_Rot13(LC_Rot5(string)) +} + +; adapted from http://langref.org/fantom+java+scala/strings/reversing-a-string/simple-substitution-cipher +; from decimal 33 '!' through 126 '~', 94 +LC_Rot47(string) { + Loop Parse, string + { + c := Asc(A_LoopField) + c += (c >= Asc("!") && c <= Asc("O") ? 47 : (c >= Asc("P") && c <= Asc("~") ? -47 : 0)) + s .= Chr(c) + } + Return s +} + +; RSHash (Robert Sedgewick's string hashing algorithm) +; from jNizM +; https://autohotkey.com/boards/viewtopic.php?p=87929#p87929 + +LC_RSHash(str) { + a := 0xF8C9, b := 0x5C6B7, h := 0 + loop, parse, str + h := h * a + Asc(A_LoopField), a *= b + return (h & 0x7FFFFFFF) +} + +LC_SecureSalted(salt, message, algo := "md5") { + hash := "" + saltedHash := %algo%(message . salt) + saltedHashR := %algo%(salt . message) + len := StrLen(saltedHash) + loop % len / 2 + { + byte1 := "0x" . SubStr(saltedHash, 2 * A_index - 1, 2) + byte2 := "0x" . SubStr(saltedHashR, 2 * A_index - 1, 2) + SetFormat, integer, hex + hash .= StrLen(ns := SubStr(byte1 ^ byte2, 3)) < 2 ? "0" ns : ns + } + SetFormat, integer, dez + return hash +} + +LC_SHA(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x8004, encoding) +} +LC_HexSHA(hexstring) { + return LC_CalcHexHash(hexstring, 0x8004) +} +LC_FileSHA(filename) { + return LC_CalcFileHash(filename, 0x8004, 64 * 1024) +} +LC_AddrSHA(addr, length) { + return LC_CalcAddrHash(addr, length, 0x8004) +} + +LC_SHA256(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x800c, encoding) +} +LC_HexSHA256(hexstring) { + return LC_CalcHexHash(hexstring, 0x800c) +} +LC_FileSHA256(filename) { + return LC_CalcFileHash(filename, 0x800c, 64 * 1024) +} +LC_AddrSHA256(addr, length) { + return LC_CalcAddrHash(addr, length, 0x800c) +} + +LC_SHA384(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x800d, encoding) +} +LC_HexSHA384(hexstring) { + return LC_CalcHexHash(hexstring, 0x800d) +} +LC_FileSHA384(filename) { + return LC_CalcFileHash(filename, 0x800d, 64 * 1024) +} +LC_AddrSHA384(addr, length) { + return LC_CalcAddrHash(addr, length, 0x800d) +} + +LC_SHA512(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x800e, encoding) +} +LC_HexSHA512(hexstring) { + return LC_CalcHexHash(hexstring, 0x800e) +} +LC_FileSHA512(filename) { + return LC_CalcFileHash(filename, 0x800e, 64 * 1024) +} +LC_AddrSHA512(addr, length) { + return LC_CalcAddrHash(addr, length, 0x800e) +} + +; Modified by GeekDude from http://goo.gl/0a0iJq +LC_UriEncode(Uri, RE="[0-9A-Za-z]") { + VarSetCapacity(Var, StrPut(Uri, "UTF-8"), 0), StrPut(Uri, &Var, "UTF-8") + While Code := NumGet(Var, A_Index - 1, "UChar") + Res .= (Chr:=Chr(Code)) ~= RE ? Chr : Format("%{:02X}", Code) + Return, Res +} + +LC_UriDecode(Uri) { + Pos := 1 + While Pos := RegExMatch(Uri, "i)(%[\da-f]{2})+", Code, Pos) + { + VarSetCapacity(Var, StrLen(Code) // 3, 0), Code := SubStr(Code,2) + Loop, Parse, Code, `% + NumPut("0x" A_LoopField, Var, A_Index-1, "UChar") + Decoded := StrGet(&Var, "UTF-8") + Uri := SubStr(Uri, 1, Pos-1) . Decoded . SubStr(Uri, Pos+StrLen(Code)+1) + Pos += StrLen(Decoded)+1 + } + Return, Uri +} + +;---------------------------------- + +LC_UrlEncode(Url) { ; keep ":/;?@,&=+$#." + return LC_UriEncode(Url, "[0-9a-zA-Z:/;?@,&=+$#.]") +} + +LC_UrlDecode(url) { + return LC_UriDecode(url) +} + +; +; Version: 2014.03.06-1518, jNizM +; see https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher +; =================================================================================== + +LC_VigenereCipher(string, key, enc := 1) { + enc := "", DllCall("user32.dll\CharUpper", "Ptr", &string, "Ptr") + , string := RegExReplace(StrGet(&string), "[^A-Z]") + loop, parse, string + { + a := Asc(A_LoopField) - 65 + , b := Asc(SubStr(key, 1 + Mod(A_Index - 1, StrLen(key)), 1)) - 65 + , enc .= Chr(Mod(a + b, 26) + 65) + } + return enc +} + +LC_VigenereDecipher(string, key) { + dec := "" + loop, parse, key + dec .= Chr(26 - (Asc(A_LoopField) - 65) + 65) + return LC_VigenereCipher(string, dec) +} + +; FUnctions and algorithm by VxE +; intergrated into libcrypt.ahk with "LC_" prefixes + +/* +#################################################################################################### +#################################################################################################### +###### ###### +###### [VxE]-251 Encryption ###### +###### & ###### +###### [VxE]-89 Encryption ###### +###### ###### +#################################################################################################### +#################################################################################################### + +[VxE] 251 encryption is a rotation-based encryption algorithm using a dynamic key and a +dynamic map. The '251' indicates the size of the map, which omits the following byte-values: +0x00 ( null byte: string terminator ) +0x09 ( tab character: common text formatting character ) +0x0A ( newline character: common text formatting character ) +0x0D ( carriage return character: common text formatting character ) +0x7F ( wierd character: ascii 'del' ) + +This encryption function also supports an 89-character map, which incorporates the byte values +between 0x20 and 0x7e, omitting 0x22, 0x27, 0x2C, 0x2F, 0x5C, and 0x60. This mode allows text value +input to be encrypted as text without high-ascii characters or non-printable characters. +*/ + +; ################################################################################################## +; ## Function shortcuts + +LC_VxE_Encrypt89( key, byref message ) { ; ---------------------------------------------------------- + Return LC_VxE_Crypt( key, message, 1, "vxe89 len" StrLen( message ) << !!A_IsUnicode ) +} ; VxE_Encrypt89( key, byref message ) ---------------------------------------------------------- + +LC_VxE_Decrypt89( key, byref message ) { ; ---------------------------------------------------------- + Return LC_VxE_Crypt( key, message, 0, "vxe89 len" StrLen( message ) << !!A_IsUnicode ) +} ; VxE_Decrypt89( key, byref message ) ---------------------------------------------------------- + +LC_VxE_Encrypt251( key, byref message, len ) { ; ---------------------------------------------------- + Return LC_VxE_Crypt( key, message, 1, "len" len ) +} ; VxE_Encrypt251( key, byref message, len ) ---------------------------------------------------- + +LC_VxE_Decrypt251( key, byref message, len ) { ; ---------------------------------------------------- + Return LC_VxE_Crypt( key, message, 0, "len" len ) +} ; VxE_Decrypt251( key, byref message, len ) ---------------------------------------------------- + +; ################################################################################################## +; ## The core function + +LC_VxE_Crypt( key, byref message, direction = 1, options="" ) { ; ----------------------------------- +; Transorms the message. 'direction' indicates whether or not to decrypt or encrypt the message. +; However, since this algorithm is symmetrical, distinguishing between 'encrypt' and 'decrypt' is +; merely for the benefit of human understanding. + +; This agorithm was developed by [VxE] in July 2010. When a key/message are passed to this function, +; it generates the rotation map using the key. Then, it traverses the bytes in the message, rotating +; their values along the map according to the key. Once the character's encoded value is determined, +; the key is augmented by a value based on the byte value. + + If !RegexMatch( options, "i)(?:len|l)\K(?:0x[\da-fA-F]+|\d+)", length ) ; check explicit length + length := StrLen( message ) << !!A_IsUnicode ; otherwise, find length. + UseVxE89 := InStr( options, "vxe89" ) ; check 'options' for text-friendly mode. + direction := 2 * ( direction = 1 ) - 1 ; coerce the 'direction' to either +1 or -1. + + w := StrLen( key ) << !!A_IsUnicode + ; 'w' holds the derived key, which is a 32-bit integer based on the key. + ; Although this doesn't seem very entropic, remember that the map is also derived from the key. + + If (UseVxE89) ; using the smaller map allows text-friendly encrypting since the small map is + Loop 126 ; composed only of low-ascii printable characters + If ( A_Index >= 32 && A_Index != 34 && A_Index != 39 && A_Index != 44 + && A_Index != 47 && A_Index != 92 && A_Index != 96 ) + map .= Chr( A_Index ) + If !UseVxE89 ; the 251 map is more suitable for non-text data + Loop 255 + If ( A_Index != 9 && A_Index != 10 && A_Index != 13 && A_Index != 127 ) + map .= Chr( A_Index ) + k := StrLen( map ) ; keep the length of the map + + Loop 9 ; pad the key up to 509 characters, mixing in digit-characters + If StrLen( key ) < 509 + key := SubStr( key Chr( 48 + A_Index ) key, 1, 509 ) + + Loop 509 ; rearrange the map, using the padded key as the selector. + { ; This is how the map becomes dynamic. 509 times, a char is selected from the map and + ; is extracted from the map string, then appended to it. At the same time, the derived key is + ; augmented by XORing it with a value based on each byte in the key. + q := *( &key + A_Index - 1 ) + pos := 1 + Mod( q * A_Index * 3, k ) + StringMid, e, map, %pos%, 1 + StringLeft, i, map, pos - 1 + StringTrimLeft, c, map, %pos% + map := i c e + w ^= q * A_Index * 1657 + } + x := 0 + Loop %length% + { + c := NumGet( message, A_Index - 1, "UChar" ) ; for each byte in the message + + If !c || !( i := InStr( map, Chr( c ), 1 ) ) + Continue ; if the character isn't in the map, just skip it. + i-- ; the map index should be zero based for easier use with Mod() function + x++ ; this tracks the actual index, not the char position. + + e := Mod( 223390000 + i + w * direction, k ) ; rotate the index along the map + + c := Asc( SubStr( map, e + 1, 1 ) ) ; lookup the character at the rotated index + + NumPut( c, message, A_Index - 1, "UChar" ) ; append the newly-mapped char to the result + + ; Finally, depending on the direction of rotation, use either the original index or + ; the rotated index to augment the derived key + If ( direction = 1 ) + c := Mod( e + x, 251 ) + Else c := Mod( i + x, 251 ) + w ^= c | c << 8 | c << 16 | c << 24 + } + return length +} ; VxE_Crypt( key, byref message, direction = 1, options="" ) ----------------------------------- + +LC_XOR_Encrypt(str,key) { + EncLen:=StrPut(Str,"UTF-16")*2 + VarSetCapacity(EncData,EncLen) + StrPut(Str,&EncData,"UTF-16") + + PassLen:=StrPut(key,"UTF-8") + VarSetCapacity(PassData,PassLen) + StrPut(key,&PassData,"UTF-8") + + LC_XOR(OutData,EncData,EncLen,PassData,PassLen) + LC_Base64_Encode(OutBase64, OutData, EncLen) + return OutBase64 +} + +LC_XOR_Decrypt(OutBase64,key) { + EncLen:=LC_Base64_Decode(OutData, OutBase64) + + PassLen:=StrPut(key,"UTF-8") + VarSetCapacity(PassData,PassLen) + StrPut(key,&PassData,"UTF-8") + + LC_XOR(EncData,OutData,EncLen,PassData,PassLen) + return StrGet(&EncData,"UTF-16") +} + +LC_XOR(byref OutData,byref EncData,EncLen,byref PassData,PassLen) +{ + VarSetCapacity(OutData,EncLen) + Loop % EncLen + NumPut(NumGet(EncData,A_Index-1,"UChar")^NumGet(PassData,Mod(A_Index-1,PassLen),"UChar"),OutData,A_Index-1,"UChar") +} diff --git a/libcrypt/libcrypt_v2.ahk2 b/libcrypt/libcrypt_v2.ahk2 new file mode 100644 index 0000000..e70f288 --- /dev/null +++ b/libcrypt/libcrypt_v2.ahk2 @@ -0,0 +1,1062 @@ +#Requires AutoHotkey v2.0 +#Warn LocalSameAsGlobal, Off + +LC_Version := "0.0.24.04" + +; ============================================================================== +; ASCII / Binary +; ============================================================================== + +LC_ASCII2Bin(s, pretty := false) { + r := "" + for i, ch in StrSplit(s) { + byte := Ord(ch), bits := "" + Loop 8 + bits := ((byte >> (A_Index - 1)) & 1) bits + r .= bits + if pretty && i < StrLen(s) + r .= " " + } + return r +} + +LC_Ascii2Bin2(Ascii) { + Out := "" + for Char in StrSplit(Ascii) + Loop 8 + Out .= !!(Ord(Char) & (1 << (8 - A_Index))) + return Out +} + +LC_Bin2Ascii(Bin) { + Bin := RegExReplace(Bin, "[^10]") + Out := "" + Loop StrLen(Bin) // 8 { + val := 0 + for Bit in StrSplit(SubStr(Bin, (A_Index - 1) * 8 + 1, 8)) + val += val + Bit + Out .= Chr(val) + } + return Out +} + +; ============================================================================== +; Binary String Encode/Decode (text <-> binary string) +; ============================================================================== + +LC_BinStr_EncodeText(Text, Pretty := false, Encoding := "UTF-8") { + Len := StrPut(Text, Encoding) - 1 + Buf := Buffer(Len) + StrPut(Text, Buf, Encoding) + BinStr := "" + LC_BinStr_Encode(&BinStr, &Buf, Len, Pretty) + return BinStr +} + +LC_BinStr_DecodeText(Text, Encoding := "UTF-8") { + Len := LC_BinStr_Decode(&Buf, Text) + return StrGet(Buf, Len, Encoding) +} + +LC_BinStr_Encode(&Out, &InBuf, InLen, Pretty := false) { + Out := "" + Loop InLen { + Byte := NumGet(InBuf, A_Index - 1, "UChar") + Loop 8 + Out .= (Byte >> (8 - A_Index)) & 1 + if Pretty + Out .= " " + } +} + +LC_BinStr_Decode(&Out, InTxt) { + InTxt := RegExReplace(InTxt, "[^01]") + ByteCount := StrLen(InTxt) // 8 + Out := Buffer(ByteCount, 0) + BitIndex := 1 + Loop ByteCount { + Byte := 0 + Loop 8 { + Byte := (Byte << 1) | SubStr(InTxt, BitIndex, 1) + BitIndex += 1 + } + NumPut("UChar", Byte, Out, A_Index - 1) + } + return ByteCount +} + +; ============================================================================== +; ASCII85 (Original + Z85) +; ============================================================================== + +LC_ASCII85_Encode(content, variant := "") { + content := StrReplace(StrReplace(content, "<~"), "~>") + bytes := [] + for ch in StrSplit(content) + bytes.Push(Ord(ch)) + variant := __LC_ASCII85_getVariant(variant) + n := bytes.Length, string := "", i := 1 + while (i <= n) { + if (i - 1 + 4 > n) + bytes.Push(0, 0, 0) + tuple := ((bytes[i] << 24) + (bytes[i + 1] << 16) + (bytes[i + 2] << 8) + bytes[i + 3]) >> 0 + if (variant["zeroTupleChar"] = "null") || (tuple > 0) { + digits := [] + Loop 5 { + digits.Push(Mod(tuple, 85)) + tuple := tuple // 85 + } + newarr := [] + for t_idx, t_val in digits + newarr.InsertAt(1, t_val) + digits := newarr + if (n < (i - 1 + 4)) + digits := __LC_ASCII85_splice(digits, n - (i - 1 + 4), 4) + for t_k, t_v in digits + string .= (variant["alphabet"] = "null") ? Chr(t_v + 33) : SubStr(variant["alphabet"], t_v + 1, 1) + } else { + string .= variant["zeroTupleChar"] + } + i += 4 + } + return string +} + +LC_ASCII85_Decode(content, variant := "") { + string := Trim(content) + variant := __LC_ASCII85_getVariant(variant) + n := StrLen(string) + bytes := [], i := 1 + while (i <= n) { + if (SubStr(string, i, 1) = variant.zeroTupleChar) { + bytes.Push(0, 0, 0, 0) + i++ + } else { + digits := [] + for character in StrSplit(SubStr(string, i, 5)) { + digit := (variant["alphabet"] = "null") ? Ord(character) - 33 : InStr(variant["alphabet"], character) - 1 + if (digit < 0 || digit > 84) + throw Error(Format("Invalid character '{1}' at index {2}", character, i + A_Index - 1)) + digits.Push(digit) + } + tuple := 0 + digits[1] * 52200625 + digits[2] * 614125 + ((i - 1 + 2 < n) ? digits[3] : 84) * 7225 + ((i - 1 + 3 < n) ? digits[4] : 84) * 85 + ((i - 1 + 4 < n) ? digits[5] : 84) + tupleBytes := [(tuple >> 24) & 0xFF, (tuple >> 16) & 0xFF, (tuple >> 8) & 0xFF, tuple & 0xFF] + if (n < i - 1 + 5) + tupleBytes := __LC_ASCII85_splice(tupleBytes, n - (i - 1 + 5), 5) + for t_v in tupleBytes + bytes.Push(t_v) + i += 5 + } + } + decoded := "" + for v in bytes + decoded .= Chr(v) + return decoded +} + +__LC_ASCII85_getVariant(variant := "") { + if InStr(variant, "z") + return {name:"Z85", label:"Z85 (ZeroMQ)", alphabet:"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#", zeroTupleChar:"null"} + return {name:"original", label:"Original", alphabet:"null", zeroTupleChar:"z"} +} + +__LC_ASCII85_splice(arr, start, deleteCount := "") { + len := arr.Length, newarr := [] + startIndex := start + if (start > len) + startIndex := len + else if (start < 0) + startIndex := len + start + if (len + start < 0) + startIndex := 0 + Loop startIndex + newarr.Push(arr[A_Index]) + if (deleteCount != "") { + if (deleteCount < 0) + deleteCount := 0 + j := 1 + startIndex + deleteCount + while (j <= len) { + newarr.Push(arr[j]) + j++ + } + } + return newarr +} + +; ============================================================================== +; Base64 / Hex via Windows CryptoAPI +; ============================================================================== + +LC_Base64_EncodeText(Text, Encoding := "UTF-8") { + Len := StrPut(Text, Encoding) - 1 + Bin := Buffer(Len) + StrPut(Text, Bin, Encoding) + Base64 := "" + LC_Base64_Encode(&Base64, &Bin, Len) + return Base64 +} + +LC_Base64_DecodeText(Text, Encoding := "UTF-8") { + Len := LC_Base64_Decode(&Bin, Text) + return StrGet(Bin, Len, Encoding) +} + +LC_Base64_Encode(&OutVar, &InVar, InLen) { + return LC_Bin2Str(&OutVar, &InVar, InLen, 0x40000001) +} + +LC_Base64_Decode(&OutVar, InVar) { + return LC_Str2Bin(&OutVar, InVar, 0x1) +} + +LC_Bin2Hex(&OutVar, &InVar, InLen, Pretty := false) { + return LC_Bin2Str(&OutVar, &InVar, InLen, Pretty ? 0xb : 0x4000000c) +} + +LC_Hex2Bin(&OutVar, &InVar) { + return LC_Str2Bin(&OutVar, &InVar, 0x8) +} + +LC_Bin2Str(&OutVar, &InVar, InLen, Flags) { + OutLen := 0 + DllCall("Crypt32\CryptBinaryToString", "ptr", InVar, "uint", InLen, "uint", Flags, "ptr", 0, "uint*", &OutLen) + OutVar := Buffer(OutLen * 2) + DllCall("Crypt32\CryptBinaryToString", "ptr", InVar, "uint", InLen, "uint", Flags, "ptr", OutVar, "uint*", &OutLen) + return OutLen +} + +LC_Str2Bin(&OutVar, InVar, Flags) { + OutLen := 0 + DllCall("Crypt32\CryptStringToBinary", "ptr", InVar, "uint", StrLen(InVar), "uint", Flags, "ptr", 0, "uint*", &OutLen, "ptr", 0, "ptr", 0) + OutVar := Buffer(OutLen) + DllCall("Crypt32\CryptStringToBinary", "ptr", InVar, "uint", StrLen(InVar), "uint", Flags, "ptr", OutVar, "uint*", &OutLen, "ptr", 0, "ptr", 0) + return OutLen +} + +; ============================================================================== +; Caesar / ROT +; ============================================================================== + +LC_Caesar(string, num := 2) { + ret := "" + for ch in StrSplit(string) { + c := Ord(ch) + if (c > 64 && c < 91) + ret .= Chr(Mod(c - 65 + num, 26) + 65) + else if (c > 96 && c < 123) + ret .= Chr(Mod(c - 97 + num, 26) + 97) + else + ret .= ch + } + return ret +} + +LC_Rot5(string) { + s := "" + for ch in StrSplit(string) { + c := Ord(ch) + s .= (c >= 48 && c <= 57) ? ((c < 53) ? c + 5 : c - 5) : c + } + return s +} + +LC_Rot13(string) { + s := "" + for ch in StrSplit(string) { + c := Ord(ch) + if ((c >= 97 && c <= 109) || (c >= 65 && c <= 77)) + c += 13 + else if ((c >= 110 && c <= 122) || (c >= 78 && c <= 90)) + c -= 13 + s .= Chr(c) + } + return s +} + +LC_Rot18(string) { + return LC_Rot13(LC_Rot5(string)) +} + +LC_Rot47(string) { + s := "" + for ch in StrSplit(string) { + c := Ord(ch) + c += (c >= 33 && c <= 79 ? 47 : (c >= 80 && c <= 126 ? -47 : 0)) + s .= Chr(c) + } + return s +} + +; ============================================================================== +; Base conversion +; ============================================================================== + +LC_To_Dec(b, n) { + d := 0, n := StrUpper(n) + for i, ch in StrSplit(n) { + d *= b, k := ch + if (k < "0" || k > "9") + k := Ord(k) - 55 + else + k := Integer(k) + d += k + } + return d +} + +LC_From_Dec(b, n) { + m := "" + Loop { + d := Mod(n, b), n //= b + m := (d < 10 ? d : Chr(d + 55)) m + if n < 1 + Break + } + return m +} + +LC_Dec2Hex(x) { + return LC_From_Dec(16, x) +} + +LC_Hex2Dec(x) { + return LC_To_Dec(16, x) +} + +LC_Numvert(num, from, to) { + return LC_From_Dec(to, LC_To_Dec(from, num)) +} + +; ============================================================================== +; Div2 +; ============================================================================== + +LC_Div2_encode(input, WithAutoTrim := true, numproc := 1) { + if WithAutoTrim + input := StrReplace(input, A_Space, "_") + Loop numproc { + final := "", inputlen := StrLen(input) + divmax := Ceil((0.5 * inputlen) + 1) + Loop inputlen { + temp := SubStr(input, A_Index, 1) + q := inputlen + 1 - A_Index + temp2 := SubStr(input, q, 1) + if (A_Index < divmax) { + final .= temp + if (A_Index != q) + final .= temp2 + } else + Break + } + input := final + } + return final +} + +LC_Div2_decode(input, WithAutoTrim := true, numproc := 1) { + if WithAutoTrim + input := StrReplace(input, A_Space, "_") + Loop numproc { + i := 1, final := "", inputlen := StrLen(input) + loopc := Ceil(inputlen * (1/2)) + Loop loopc { + if (i <= inputlen) + final .= SubStr(input, i, 1) + i += 2 + } + i := inputlen + Loop loopc { + if (i <= inputlen) { + if (Mod(SubStr(i, 0, 1) + 0, 2) = 1) { + if (i != 1) + final .= SubStr(input, i - 1, 1) + } else { + final .= SubStr(input, i, 1) + } + } + i -= 2 + } + input := final + } + return final +} + +; ============================================================================== +; URI / URL +; ============================================================================== + +LC_UriEncode(Uri, RE := "[0-9A-Za-z]") { + Var := Buffer(StrPut(Uri, "UTF-8") - 1), StrPut(Uri, Var, "UTF-8"), Res := "" + Loop Var.Size { + Code := NumGet(Var, A_Index - 1, "UChar") + Res .= (Chr(Code) ~= RE) ? Chr(Code) : Format("%{:02X}", Code) + } + return Res +} + +LC_UriDecode(Uri, Encoding := "UTF-8") { + Pos := 1 + while Pos := RegExMatch(Uri, "i)(%[\da-f]{2})+", &Code, Pos) { + Var := Buffer(StrLen(Code[0]) // 3, 0), CodeTxt := SubStr(Code[0], 2) + Loop Var.Size + NumPut("UChar", Integer("0x" SubStr(CodeTxt, (A_Index - 1) * 2 + 1, 2)), Var, A_Index - 1) + Decoded := StrGet(Var, Var.Size, Encoding) + Uri := SubStr(Uri, 1, Pos - 1) Decoded SubStr(Uri, Pos + StrLen(Code[0])) + Pos += StrLen(Decoded) + 1 + } + return Uri +} + +LC_UrlEncode(Url) { + return LC_UriEncode(Url, "[!#$&-;=?-Z_a-z~]") +} + +LC_UrlDecode(url) { + return LC_UriDecode(url) +} + +; ============================================================================== +; Vigenere +; ============================================================================== + +LC_VigenereCipher(string, key, enc := 1) { + enc := "" + DllCall("user32\CharUpperW", "ptr", StrPtr(string)) + string := RegExReplace(string, "[^A-Z]") + for ch in StrSplit(string) { + a := Ord(ch) - 65 + b := Ord(SubStr(key, 1 + Mod(A_Index - 1, StrLen(key)), 1)) - 65 + enc .= Chr(Mod(a + b, 26) + 65) + } + return enc +} + +LC_VigenereDecipher(string, key) { + dec := "" + for ch in StrSplit(key) + dec .= Chr(26 - (Ord(ch) - 65) + 65) + return LC_VigenereCipher(string, dec) +} + +; ============================================================================== +; CryptoAPI Hash Core (CalcAddrHash etc.) +; ============================================================================== + +LC_CalcAddrHash(addr, length, algid, &hash := 0, &hashlength := 0) { + static h := [0,1,2,3,4,5,6,7,8,9,"a","b","c","d","e","f"] + hProv := hHash := o := "" + if DllCall("advapi32\CryptAcquireContext", "ptr*", &hProv, "ptr", 0, "ptr", 0, "uint", 24, "uint", 0xF0000000) = 0 { + if DllCall("advapi32\CryptCreateHash", "ptr", hProv, "uint", algid, "uint", 0, "uint", 0, "ptr*", &hHash) = 0 { + if DllCall("advapi32\CryptHashData", "ptr", hHash, "ptr", addr, "uint", length, "uint", 0) = 0 { + if DllCall("advapi32\CryptGetHashParam", "ptr", hHash, "uint", 2, "ptr", 0, "uint*", &hashlength, "uint", 0) = 0 { + hash := Buffer(hashlength, 0) + if DllCall("advapi32\CryptGetHashParam", "ptr", hHash, "uint", 2, "ptr", hash, "uint*", &hashlength, "uint", 0) = 0 { + Loop hashlength { + v := NumGet(hash, A_Index - 1, "UChar") + o .= h[(v >> 4) + 1] h[(v & 0xF) + 1] + } + } + } + } + DllCall("advapi32\CryptDestroyHash", "ptr", hHash) + } + DllCall("advapi32\CryptReleaseContext", "ptr", hProv, "uint", 0) + } + return o +} + +LC_CalcStringHash(string, algid, encoding := "UTF-8", &hash := 0, &hashlength := 0) { + chrlength := (encoding = "CP1200" || encoding = "UTF-16") ? 2 : 1 + length := (StrPut(string, encoding) - 1) * chrlength + data := Buffer(length, 0) + StrPut(string, data, length // chrlength, encoding) + return LC_CalcAddrHash(data, length, algid, &hash, &hashlength) +} + +LC_CalcHexHash(hexstring, algid) { + length := StrLen(hexstring) // 2 + data := Buffer(length, 0) + Loop length + NumPut("UChar", Integer("0x" SubStr(hexstring, 2 * A_Index - 1, 2)), data, A_Index - 1) + return LC_CalcAddrHash(data, length, algid) +} + +LC_CalcFileHash(filename, algid, chunkSize := 0, &hash := 0, &hashlength := 0) { + fpos := "" + f := FileOpen(filename, "r") + if !f + return "" + f.Pos := 0 + if (!chunkSize && f.Length > 0x7FFFFFFF) + return "" + if (!chunkSize) { + data := Buffer(f.Length, 0) + f.RawRead(data, f.Length) + return LC_CalcAddrHash(data, f.Length, algid, &hash, &hashlength) + } + hashlength := 0 + while (f.Pos < f.Length) { + readlength := (f.Length - fpos > chunkSize) ? chunkSize : f.Length - f.Pos + data := Buffer(hashlength + readlength, 0) + DllCall("RtlMoveMemory", "ptr", data, "ptr", hash, "ptr", hashlength) + f.RawRead(data, hashlength + readlength) + h := LC_CalcAddrHash(data, hashlength + readlength, algid, &hash, &hashlength) + } + return h +} + +; ============================================================================== +; MD2 / MD4 / MD5 / SHA / SHA256 / SHA384 / SHA512 wrappers +; ============================================================================== + +LC_MD2(string, encoding := "UTF-8") => LC_CalcStringHash(string, 0x8001, encoding) +LC_HexMD2(hexstring) => LC_CalcHexHash(hexstring, 0x8001) +LC_FileMD2(filename) => LC_CalcFileHash(filename, 0x8001, 64*1024) +LC_AddrMD2(addr, length) => LC_CalcAddrHash(addr, length, 0x8001) + +LC_MD4(string, encoding := "UTF-8") => LC_CalcStringHash(string, 0x8002, encoding) +LC_HexMD4(hexstring) => LC_CalcHexHash(hexstring, 0x8002) +LC_FileMD4(filename) => LC_CalcFileHash(filename, 0x8002, 64*1024) +LC_AddrMD4(addr, length) => LC_CalcAddrHash(addr, length, 0x8002) + +LC_MD5(string, encoding := "UTF-8") => LC_CalcStringHash(string, 0x8003, encoding) +LC_HexMD5(hexstring) => LC_CalcHexHash(hexstring, 0x8003) +LC_FileMD5(filename) => LC_CalcFileHash(filename, 0x8003, 64*1024) +LC_AddrMD5(addr, length) => LC_CalcAddrHash(addr, length, 0x8003) + +LC_SHA(string, encoding := "UTF-8") => LC_CalcStringHash(string, 0x8004, encoding) +LC_HexSHA(hexstring) => LC_CalcHexHash(hexstring, 0x8004) +LC_FileSHA(filename) => LC_CalcFileHash(filename, 0x8004, 64*1024) +LC_AddrSHA(addr, length) => LC_CalcAddrHash(addr, length, 0x8004) + +LC_SHA256(string, encoding := "UTF-8") => LC_CalcStringHash(string, 0x800C, encoding) +LC_HexSHA256(hexstring) => LC_CalcHexHash(hexstring, 0x800C) +LC_FileSHA256(filename) => LC_CalcFileHash(filename, 0x800C, 64*1024) +LC_AddrSHA256(addr, length) => LC_CalcAddrHash(addr, length, 0x800C) + +LC_SHA384(string, encoding := "UTF-8") => LC_CalcStringHash(string, 0x800D, encoding) +LC_HexSHA384(hexstring) => LC_CalcHexHash(hexstring, 0x800D) +LC_FileSHA384(filename) => LC_CalcFileHash(filename, 0x800D, 64*1024) +LC_AddrSHA384(addr, length) => LC_CalcAddrHash(addr, length, 0x800D) + +LC_SHA512(string, encoding := "UTF-8") => LC_CalcStringHash(string, 0x800E, encoding) +LC_HexSHA512(hexstring) => LC_CalcHexHash(hexstring, 0x800E) +LC_FileSHA512(filename) => LC_CalcFileHash(filename, 0x800E, 64*1024) +LC_AddrSHA512(addr, length) => LC_CalcAddrHash(addr, length, 0x800E) + +; ============================================================================== +; CRC32 +; ============================================================================== + +LC_CRC32(string, encoding := "UTF-8") { + chrlength := (encoding = "CP1200" || encoding = "UTF-16") ? 2 : 1 + length := (StrPut(string, encoding) - 1) * chrlength + data := Buffer(length, 0) + StrPut(string, data, length // chrlength, encoding) + hMod := DllCall("Kernel32\LoadLibraryW", "str", "Ntdll.dll") + CRC32 := DllCall("Ntdll\RtlComputeCrc32", "uint", 0, "ptr", data, "uint", length, "uint") + CRC := Format("{:08X}", CRC32) + DllCall("User32\CharLowerW", "str", CRC) + DllCall("Kernel32\FreeLibrary", "ptr", hMod) + return CRC +} + +LC_HexCRC32(hexstring) { + length := StrLen(hexstring) // 2 + data := Buffer(length, 0) + Loop length + NumPut("UChar", Integer("0x" SubStr(hexstring, 2 * A_Index - 1, 2)), data, A_Index - 1) + hMod := DllCall("Kernel32\LoadLibraryW", "str", "Ntdll.dll") + CRC32 := DllCall("Ntdll\RtlComputeCrc32", "uint", 0, "ptr", data, "uint", length, "uint") + CRC := Format("{:08X}", CRC32) + DllCall("User32\CharLowerW", "str", CRC) + DllCall("Kernel32\FreeLibrary", "ptr", hMod) + return CRC +} + +LC_FileCRC32(sFile := "", cSz := 4) { + Bytes := "" + cSz := (cSz < 0 || cSz > 8) ? 2**22 : 2**(18 + cSz) + BufferObj := Buffer(cSz, 0) + hFil := DllCall("Kernel32\CreateFileW", "str", sFile, "uint", 0x80000000, "uint", 3, "int", 0, "uint", 3, "uint", 0, "int", 0, "ptr") + if (hFil < 1) + return hFil + hMod := DllCall("Kernel32\LoadLibraryW", "str", "Ntdll.dll") + CRC32 := 0 + fSz := NumGet(BufferObj, 0, "int64") + Loop (fSz // cSz + !!Mod(fSz, cSz)) { + DllCall("Kernel32\ReadFile", "ptr", hFil, "ptr", BufferObj, "uint", cSz, "uint*", &Bytes, "uint", 0) + CRC32 := DllCall("Ntdll\RtlComputeCrc32", "uint", CRC32, "ptr", BufferObj, "uint", Bytes, "uint") + } + DllCall("Kernel32\CloseHandle", "ptr", hFil) + CRC32 := Format("{:08X}", CRC32) + DllCall("User32\CharLowerW", "str", CRC32) + DllCall("Kernel32\FreeLibrary", "ptr", hMod) + return CRC32 +} + +; ============================================================================== +; HMAC +; ============================================================================== + +LC_HMAC(Key, Message, Algo := "MD5") { + static Algorithms := {MD2:{ID:0x8001,Size:64}, MD4:{ID:0x8002,Size:64}, MD5:{ID:0x8003,Size:64}, SHA:{ID:0x8004,Size:64}, SHA256:{ID:0x800C,Size:64}, SHA384:{ID:0x800D,Size:128}, SHA512:{ID:0x800E,Size:128}} + static iconst := 0x36, oconst := 0x5C + if !Algorithms.Has(Algo) + return "" + AlgID := Algorithms[Algo].ID, BlockSize := Algorithms[Algo].Size + MsgLen := StrPut(Message, "UTF-8") - 1 + KeyLen := StrPut(Key, "UTF-8") - 1 + K := Buffer(KeyLen + 1, 0) + StrPut(Key, K, KeyLen, "UTF-8") + KeyHash := KeyHashLen := "" + if (KeyLen > BlockSize) + LC_CalcAddrHash(K, KeyLen, AlgID, &KeyHash, &KeyHashLen) + ipad := Buffer(BlockSize + MsgLen, iconst) + Addr := KeyLen > BlockSize ? KeyHash : K + Length := KeyLen > BlockSize ? KeyHashLen : KeyLen + i := 0 + while (i < Length) { + NumPut(NumGet(Addr, i, "UChar") ^ iconst, ipad, i, "UChar") + i++ + } + if (MsgLen) + StrPut(Message, Buffer(ipad.Ptr + BlockSize, MsgLen), MsgLen, "UTF-8") + InnerHash := InnerHashLen := "" + LC_CalcAddrHash(ipad, BlockSize + MsgLen, AlgID, &InnerHash, &InnerHashLen) + opad := Buffer(BlockSize + InnerHashLen, oconst) + Addr := KeyLen > BlockSize ? KeyHash : K + Length := KeyLen > BlockSize ? KeyHashLen : KeyLen + i := 0 + while (i < Length) { + NumPut(NumGet(Addr, i, "UChar") ^ oconst, opad, i, "UChar") + i++ + } + i := 0 + while (i < InnerHashLen) { + NumPut(NumGet(InnerHash, i, "UChar"), Buffer(opad.Ptr + BlockSize + i, 1), 0, "UChar") + i++ + } + return LC_CalcAddrHash(opad, BlockSize + InnerHashLen, AlgID) +} + +; ============================================================================== +; L64 / L128 Hash (Laszlo) +; ============================================================================== + +__LC_LHashTable := [] + +LC_L64Hash(x) { + global __LC_LHashTable + if __LC_LHashTable.Length = 0 + __LC_LHash_LHashInit() + R := 0 + for ch in StrSplit(x) { + i := (R >> 56) & 255 + R := ((R << 8) + Ord(ch)) ^ __LC_LHashTable[i + 1] + } + return __LC_LHash_Hex8(R >> 32) . __LC_LHash_Hex8(R) +} + +LC_L128Hash(x) { + global __LC_LHashTable + if __LC_LHashTable.Length = 0 + __LC_LHash_LHashInit() + S := 0, R := -1 + for ch in StrSplit(x) { + i := (R >> 56) & 255 + R := ((R << 8) + Ord(ch)) ^ __LC_LHashTable[i + 1] + i := (S >> 56) & 255 + S := ((S << 8) + Ord(ch)) - __LC_LHashTable[i + 1] + } + return __LC_LHash_Hex8(R >> 32) . __LC_LHash_Hex8(R) . __LC_LHash_Hex8(S >> 32) . __LC_LHash_Hex8(S) +} + +__LC_LHash_Hex8(i) { + i := 0x100000000 | (i & 0xFFFFFFFF) + return SubStr(i, -7) +} + +__LC_LHash_LHashInit() { + global __LC_LHashTable + u := 0, v := 0 + Loop 256 { + i := A_Index - 1 + __LC_LHASH_TEA(&u, &v, 1, 22, 333, 4444, 8) + __LC_LHashTable.Push((u << 32) | v) + } +} + +__LC_LHASH_TEA(&y, &z, k0, k1, k2, k3, n := 32) { + s := 0, d := 0x9E3779B9 + Loop n { + k := [k0,k1,k2,k3][Mod(s, 4) + 1] + y := 0xFFFFFFFF & (y + (((z << 4) ^ (z >> 5)) + z ^ s + k)) + s := 0xFFFFFFFF & (s + d) + k := [k0,k1,k2,k3][Mod(s >> 11, 4) + 1] + z := 0xFFFFFFFF & (z + (((y << 4) ^ (y >> 5)) + y ^ s + k)) + } +} + +; ============================================================================== +; nnnik21 encryption +; ============================================================================== + +LC_nnnik21_encryptStr(str := "", pass := "") { + if !(enclen := (StrPut(str, "UTF-16") * 2)) + return "Error: Nothing to Encrypt" + if !(passlen := StrPut(pass, "UTF-8") - 1) + return "Error: No Pass" + enclen := Mod(enclen, 4) ? enclen : enclen - 2 + encbin := Buffer(enclen, 0) + StrPut(str, encbin, enclen // 2, "UTF-16") + passlen += Mod((4 - Mod(passlen, 4)), 4) + passbin := Buffer(passlen, 0) + StrPut(pass, passbin, StrLen(pass), "UTF-8") + LC_nnnik21_encryptbin(&encbin, encbin.Size, &passbin, passbin.Size) + Text := "" + LC_Base64_Encode(&Text, &encbin, encbin.Size) + return Text +} + +LC_nnnik21_decryptStr(str := "", pass := "") { + if !(StrPut(str, "UTF-16") * 2) + return "Error: Nothing to Decrypt" + if !(passlen := StrPut(pass, "UTF-8") - 1) + return "Error: No Pass" + passlen += Mod((4 - Mod(passlen, 4)), 4) + passbin := Buffer(passlen, 0) + StrPut(pass, passbin, StrLen(pass), "UTF-8") + encbin := Buffer(0) + enclen := LC_Base64_Decode(&encbin, str) + LC_nnnik21__decryptbin(&encbin, encbin.Size, &passbin, passbin.Size) + return StrGet(encbin, encbin.Size, "UTF-16") +} + +LC_nnnik21_encryptbin(&pBin1, sBin1, &pBin2, sBin2) { + b := 0 + Loop sBin1 // 4 { + a := NumGet(pBin1, sBin1 - A_Index * 4, "UInt") + NumPut(a + b, pBin1, sBin1 - A_Index * 4, "UInt") + b := (a + b) * a + } + Loop sBin2 // 4 { + c := NumGet(pBin2, (A_Index - 1) * 4, "UInt") + b := 0 + Loop sBin1 // 4 { + a := NumGet(pBin1, (A_Index - 1) * 4, "UInt") + NumPut((a + b) ^ c, pBin1, (A_Index - 1) * 4, "UInt") + b := (a + b) * a + } + } +} + +LC_nnnik21__decryptbin(&pBin1, sBin1, &pBin2, sBin2) { + Loop sBin2 // 4 { + c := NumGet(pBin2, sBin2 - A_Index * 4, "UInt") + b := 0 + Loop sBin1 // 4 { + a := NumGet(pBin1, (A_Index - 1) * 4, "UInt") + a := (a ^ c) - b + NumPut(a, pBin1, (A_Index - 1) * 4, "UInt") + b := (a + b) * a + } + } + b := 0 + Loop sBin1 // 4 { + a := NumGet(pBin1, sBin1 - A_Index * 4, "UInt") + a := a - b + NumPut(a, pBin1, sBin1 - A_Index * 4, "UInt") + b := (a + b) * a + } +} + +; ============================================================================== +; RC4 +; ============================================================================== + +LC_RC4_Encrypt(Data, Pass) { + b := 0, j := 0, Key := [], sBox := [], Result := "" + Loop 256 { + a := A_Index - 1 + Key[a] := Ord(SubStr(Pass, Mod(a, StrLen(Pass)) + 1, 1)) + sBox[a] := a + } + Loop 256 { + a := A_Index - 1 + b := (b + sBox[a] + Key[a]) & 255 + t := sBox[a], sBox[a] := sBox[b], sBox[b] := t + } + for ch in StrSplit(Data) { + i := A_Index & 255 + j := (sBox[i] + j) & 255 + k := sBox[(sBox[i] + sBox[j]) & 255] + t := sBox[i], sBox[i] := sBox[j], sBox[j] := t + Result .= Format("{:02x}", Ord(ch) ^ sBox[k]) + } + return Result +} + +LC_RC4_Decrypt(Data, Pass) { + b := 0, j := 0, Key := [], sBox := [], Result := "" + Loop 256 { + a := A_Index - 1 + Key[a] := Ord(SubStr(Pass, Mod(a, StrLen(Pass)) + 1, 1)) + sBox[a] := a + } + Loop 256 { + a := A_Index - 1 + b := (b + sBox[a] + Key[a]) & 255 + t := sBox[a], sBox[a] := sBox[b], sBox[b] := t + } + Loop StrLen(Data) // 2 { + i := A_Index & 255 + j := (sBox[i] + j) & 255 + k := sBox[(sBox[i] + sBox[j]) & 255] + t := sBox[i], sBox[i] := sBox[j], sBox[j] := t + Result .= Chr((Integer("0x" SubStr(Data, (2 * A_Index) - 1, 2))) ^ sBox[k]) + } + return Result +} + +LC_RC4(RC4Data, RC4Pass) { + RC4PassLen := StrLen(RC4Pass), Key := [], sBox := [], b := 0, RC4Result := "", i := 0, j := 0 + Loop 256 { + a := A_Index - 1 + ModVal := Mod(a, RC4PassLen) + 1 + c := SubStr(RC4Pass, ModVal, 1) + Key[a] := Ord(c), sBox[a] := a + } + Loop 256 { + a := A_Index - 1 + b := Mod(b + sBox[a] + Key[a], 256) + T := sBox[a], sBox[a] := sBox[b], sBox[b] := T + } + for ch in StrSplit(RC4Data) { + i := Mod(i + 1, 256) + j := Mod(sBox[i] + j, 256) + k := sBox[Mod(sBox[i] + sBox[j], 256)] + c := Ord(ch) ^ k + c := (c = 0) ? k : c + RC4Result .= Chr(c) + } + return RC4Result +} + +; ============================================================================== +; RSHash / SecureSalted +; ============================================================================== + +LC_RSHash(str) { + a := 0xF8C9, b := 0x5C6B7, h := 0 + for ch in StrSplit(str) { + h := h * a + Ord(ch) + a *= b + } + return h & 0x7FFFFFFF +} + +LC_SecureSalted(salt, message, algo := "md5") { + hash := "" + funcName := "LC_" algo + saltedHash := %funcName%(message . salt) + saltedHashR := %funcName%(salt . message) + len := StrLen(saltedHash) + Loop len // 2 { + byte1 := "0x" SubStr(saltedHash, 2 * A_Index - 1, 2) + byte2 := "0x" SubStr(saltedHashR, 2 * A_Index - 1, 2) + ns := SubStr(byte1 ^ byte2, 3) + hash .= (StrLen(ns) < 2 ? "0" ns : ns) + } + return hash +} + +; ============================================================================== +; VxE 89 / 251 +; ============================================================================== + +LC_VxE_Encrypt89(key, &message) { + return LC_VxE_Crypt(key, &message, 1, "vxe89 len " StrLen(message)) +} + +LC_VxE_Decrypt89(key, &message) { + return LC_VxE_Crypt(key, &message, 0, "vxe89 len " StrLen(message)) +} + +LC_VxE_Encrypt251(key, &message, len) { + return LC_VxE_Crypt(key, &message, 1, "len " len) +} + +LC_VxE_Decrypt251(key, &message, len) { + return LC_VxE_Crypt(key, &message, 0, "len " len) +} + +LC_VxE_Crypt(key, &message, direction := 1, options := "") { + length := "" + if RegExMatch(options, "i)(?:len|l)\K(?:0x[\da-fA-F]+|\d+)", &m) + length := Integer(m[0]) + if length = "" + length := StrLen(message) + UseVxE89 := InStr(options, "vxe89") + direction := 2 * (direction = 1) - 1 + w := StrLen(key) + map := "" + if UseVxE89 { + Loop 126 + if (A_Index >= 32 && A_Index != 34 && A_Index != 39 && A_Index != 44 && A_Index != 47 && A_Index != 92 && A_Index != 96) + map .= Chr(A_Index) + } else { + Loop 255 + if (A_Index != 9 && A_Index != 10 && A_Index != 13 && A_Index != 127) + map .= Chr(A_Index) + } + k := StrLen(map) + Loop 9 + if StrLen(key) < 509 + key := SubStr(key Chr(48 + A_Index) key, 1, 509) + Loop 509 { + q := NumGet(StrPtr(key) + A_Index - 1, "UChar") + pos := 1 + Mod(q * A_Index * 3, k) + e := SubStr(map, pos, 1) + i := SubStr(map, 1, pos - 1) + c := SubStr(map, pos + 1) + map := i c e + w ^= q * A_Index * 1657 + } + x := 0 + Loop length { + c := NumGet(message, A_Index - 1, "UChar") + if !c || !(i := InStr(map, Chr(c), 1)) + Continue + i-- + x++ + e := Mod(223390000 + i + w * direction, k) + c := Ord(SubStr(map, e + 1, 1)) + NumPut(c, message, A_Index - 1, "UChar") + if (direction = 1) + c := Mod(e + x, 251) + else + c := Mod(i + x, 251) + w ^= c | c << 8 | c << 16 | c << 24 + } + return length +} + +; ============================================================================== +; XOR +; ============================================================================== + +LC_XOR_Encrypt(str, key) { + EncLen := StrPut(str, "UTF-16") * 2 + EncData := Buffer(EncLen, 0) + StrPut(str, EncData, EncLen // 2, "UTF-16") + PassLen := StrPut(key, "UTF-8") - 1 + PassData := Buffer(PassLen, 0) + StrPut(key, PassData, StrLen(key), "UTF-8") + OutData := Buffer(0) + LC_XOR(&OutData, &EncData, EncLen, &PassData, PassLen) + OutBase64 := "" + LC_Base64_Encode(&OutBase64, &OutData, OutData.Size) + return OutBase64 +} + +LC_XOR_Decrypt(OutBase64, key) { + OutData := Buffer(0) + EncLen := LC_Base64_Decode(&OutData, OutBase64) + PassLen := StrPut(key, "UTF-8") - 1 + PassData := Buffer(PassLen, 0) + StrPut(key, PassData, StrLen(key), "UTF-8") + EncData := Buffer(0) + LC_XOR(&EncData, &OutData, EncLen, &PassData, PassLen) + return StrGet(EncData, EncData.Size, "UTF-16") +} + +LC_XOR(&OutData, &EncData, EncLen, &PassData, PassLen) { + OutData := Buffer(EncLen, 0) + Loop EncLen + NumPut(NumGet(EncData, A_Index - 1, "UChar") ^ NumGet(PassData, Mod(A_Index - 1, PassLen), "UChar"), OutData, A_Index - 1, "UChar") +} + +; ============================================================================== +; soupRot class +; ============================================================================== + +class LC_soupRot { + enc(str, mult, junk := 0) { + str := LC_Base64_EncodeText(str) + rotBase := StrLen(str) * mult + nStr := "" + i := 0 + for a in StrSplit(str) { + i++ + rot := Mod(rotBase * i, 94) + nC := Ord(a) + rot + while (nC > 126 || nC < 32) { + if (nC > 126) + nC -= 94 + else if (nC < 32) + nC += 94 + } + nStr .= Chr(nC) + if (junk) + nStr .= this._randStr(junk, junk, 1234) + } + return nStr + } + dec(str, mult, junk := 0) { + i := 0, rotBase := StrLen(str) * mult // (junk + 1), nStr := "", skip := 0 + for a in StrSplit(str) { + if (skip) { + skip-- + continue + } + i++ + rot := Mod(rotBase * i, 94) + nC := Ord(a) - rot + while (nC > 126 || nC < 32) { + if (nC > 126) + nC -= 94 + else if (nC < 32) + nC += 94 + } + nStr .= Chr(nC) + if (junk) + skip := junk + } + return RTrim(LC_Base64_DecodeText(nStr), Chr(65533)) + } + _randStr(lowerBound, upperBound, mode := 1) { + if (!this._isDigit(lowerBound) || !this._isDigit(upperBound) || !this._isDigit(mode)) + return -1 + str := "" + Loop this._rand(lowerBound, upperBound) { + t := "" + if (StrLen(mode) = 1) + t := mode + else { + while (!this._ifContains(mode, t)) + t := this._rand(1, 4) + } + if (t = 1) + str .= Chr(this._rand(97, 122)) + else if (t = 2) + str .= Chr(this._rand(65, 90)) + else if (t = 3) + str .= this._rand(0, 9) + else if (t = 4) { + i := this._rand(1, 4) + str .= i = 1 ? Chr(this._rand(33, 47)) : i = 2 ? Chr(this._rand(58, 64)) : i = 3 ? Chr(this._rand(91, 96)) : Chr(this._rand(123, 126)) + } + } + return str + } + _rand(lowerBound, upperBound) { + return Random(lowerBound, upperBound) + } + _ifContains(haystack, needle) { + return InStr(haystack, needle) != 0 + } + _isDigit(innum) { + return InStr("0123456789", innum) != 0 + } +} diff --git a/libcrypt/testALTlibcrypt.ahk2 b/libcrypt/testALTlibcrypt.ahk2 new file mode 100644 index 0000000..e7e3268 --- /dev/null +++ b/libcrypt/testALTlibcrypt.ahk2 @@ -0,0 +1,1305 @@ +LC_Version := "0.0.24.04" +#Requires Autohotkey v2.0 + +LC_ASCII2Bin(s, pretty := 0) { + r := "" + l := StrLen(s) + for i, ch in StrSplit(s) { + byte := Ord(ch) + bits := "" + Loop 8 { + bit := (byte & (1 << (A_Index - 1))) ? "1" : "0" + bits := bit bits + } + r .= bits + if (pretty && i < l) + r .= " " + } + return r +} + +LC_Ascii2Bin2(Ascii) { + Out := "" + for Char in StrSplit(Ascii) + Loop 8 + Out .= !!(Ord(Char) & (1 << (8 - A_Index))) + return Out +} + +LC_Bin2Ascii(Bin) { + Bin := RegExReplace(Bin, "[^10]") + Loop StrLen(Bin) / 8 { + Asc := 0 + for Bit in StrSplit(SubStr(Bin, (A_Index - 1) * 8 + 1, 8)) + Asc += Asc + Bit + Out .= Chr(Asc) + } + return Out +} + +LC_BinStr_EncodeText(Text, Pretty := False, Encoding := "UTF-8") { + Len := StrPut(Text, Encoding) + Buf := Buffer(Len) + StrPut(Text, Buf, Encoding) + BinStr := "" + LC_BinStr_Encode(&BinStr, &Buf, Len, Pretty) + return BinStr +} + +LC_BinStr_DecodeText(Text, Encoding := "UTF-8") { + Len := LC_BinStr_Decode(&Buf, Text) ; Buf wird als Buffer gefüllt, Len = Bytes + return StrGet(Buf, Len, Encoding) +} + +LC_BinStr_Encode(&Out, &InBuf, InLen, Pretty := False) { + Out := "" + Loop InLen { + Byte := NumGet(InBuf, A_Index - 1, "UChar") + Loop 8 + Out .= (Byte >> (8 - A_Index)) & 1 + if Pretty + Out .= " " + } +} + +LC_BinStr_Decode(&Out, InTxt) { + ; Optional: nur 0/1 behalten, falls In Leerzeichen o.ä. enthalten kann + ; In := RegExReplace(In, "[^01]") + + ByteCount := StrLen(InTxt) // 8 + Out := Buffer(ByteCount, 0) + BitIndex := 1 + + Loop ByteCount { + Byte := 0 + Loop 8 { + Byte := (Byte << 1) | SubStr(InTxt, BitIndex, 1) + BitIndex += 1 + } + NumPut("UChar", Byte, Out, A_Index - 1) + } + + return ByteCount +} + +; implemented in ahk by joedf +; based on https://github.com/cryptii/cryptii/blob/4a0a58318d093c4c6e3333b3f296ad7c96309629/src/Encoder/Ascii85.js + +/** + * Performs encode on given content. + * @param {String} content + * @param {String} variant + * @return {String} Encoded content + */ +LC_ASCII85_Encode(content, variant := "") { + content := StrReplace(content, "<~") + content := StrReplace(content, "~>") + + bytes := [] + for ch in StrSplit(content) + bytes.Push(Ord(ch)) + + variant := __LC_ASCII85_getVariant(variant) + n := bytes.Length + + string := "" + i := 1 + while (i <= n) { + if (i - 1 + 4 > n) + bytes.Push(0, 0, 0) + + tuple := ((bytes[i] << 24) + + (bytes[i + 1] << 16) + + (bytes[i + 2] << 8) + + bytes[i + 3]) >> 0 + + if (variant["zeroTupleChar"] = "null") || (tuple > 0) { + digits := [] + Loop 5 { + digits.Push(Mod(tuple, 85)) + tuple := tuple // 85 + } + + newarr := [] + for t_idx, t_val in digits + newarr.InsertAt(1, t_val) + digits := newarr + + if (n < (i - 1 + 4)) + digits := __LC_ASCII85_splice(digits, n - (i - 1 + 4), 4) + + for t_k, t_v in digits + string .= (variant["alphabet"] = "null") + ? Chr(t_v + 33) + : SubStr(variant["alphabet"], t_v + 1, 1) + + } else { + string .= variant["zeroTupleChar"] + } + + i += 4 + } + + return string +} + +LC_ASCII85_Decode(content, variant := "") { + string := Trim(content) + variant := __LC_ASCII85_getVariant(variant) + n := StrLen(string) + + bytes := [] + i := 1 + while (i <= n) { + if (SubStr(string, i, 1) = variant.zeroTupleChar) { + bytes.Push(0, 0, 0, 0) + i++ + } else { + digits := [] + for character in StrSplit(SubStr(string, i, 5)) { + digit := (variant["alphabet"] = "null") + ? Ord(character) - 33 + : InStr(variant["alphabet"], character) - 1 + if (digit < 0 || digit > 84) + throw Error(Format("Invalid character '{1}' at index {2}", character, i + A_Index - 1)) + digits.Push(digit) + } + + tuple := 0 + + digits[1] * 52200625 + + digits[2] * 614125 + + ((i - 1 + 2 < n) ? digits[3] : 84) * 7225 + + ((i - 1 + 3 < n) ? digits[4] : 84) * 85 + + ((i - 1 + 4 < n) ? digits[5] : 84) + + tupleBytes := [ + (tuple >> 24) & 0xFF, + (tuple >> 16) & 0xFF, + (tuple >> 8) & 0xFF, + tuple & 0xFF + ] + + if (n < i - 1 + 5) + tupleBytes := __LC_ASCII85_splice(tupleBytes, n - (i - 1 + 5), 5) + + for t_v in tupleBytes + bytes.Push(t_v) + + i += 5 + } + } + + decoded := "" + for v in bytes + decoded .= Chr(v) + + return decoded +} + +__LC_ASCII85_getVariant(variant := "") { + if InStr(variant, "z") + return { name: "Z85" + , label: "Z85 (ZeroMQ)" + , alphabet: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#" + , zeroTupleChar: "null" } + return { name: "original" + , label: "Original" + , alphabet: "null" + , zeroTupleChar: "z" } +} + +__LC_ASCII85_splice(arr, start, deleteCount := "") { + len := arr.Length + newarr := [] + + startIndex := start + if (start > len) + startIndex := len + else if (start < 0) + startIndex := len + start + + if (len + start < 0) + startIndex := 0 + + Loop startIndex + newarr.Push(arr[A_Index]) + + if (deleteCount != "") { + if (deleteCount < 0) + deleteCount := 0 + + j := 1 + startIndex + deleteCount + while (j <= len) { + newarr.Push(arr[j]) + j++ + } + } + + return newarr +} + +LC_Base64_EncodeText(Text, Encoding := "UTF-8") { + Len := StrPut(Text, Encoding) + Bin := Buffer(Len) + StrPut(Text, Bin, Encoding) + + Base64 := "" + LC_Base64_Encode(&Base64, &Bin, Len) + return Base64 +} + +LC_Base64_DecodeText(Text, Encoding := "UTF-8") { + Len := LC_Base64_Decode(&Bin, Text) + return StrGet(Bin, Len, Encoding) +} + +LC_Base64_Encode(&Out, &InBin, InLen) { + return LC_Bin2Str(&Out, &InBin, InLen, 0x40000001) +} + +LC_Base64_Decode(&Out, InTxt) { + ; In ist hier ein String (Base64), Out soll ein Buffer werden + return LC_Str2Bin(&Out, InTxt, 0x1) +} + + +LC_Bin2Hex(&Out, &InBin, InLen, Pretty := False) { + return LC_Bin2Str(&Out, &InBin, InLen, Pretty ? 0xb : 0x4000000c) +} + +LC_Hex2Bin(&Out, InHex) { + return LC_Str2Bin(&Out, InHex, 0x8) +} + +LC_Bin2Str(&Out, &InBin, InLen, Flags) { + DllCall("Crypt32.dll\CryptBinaryToString", "ptr", InBin, "uint", InLen, "uint", Flags, "ptr", 0, "uint*", &OutLen) + Out := Buffer(OutLen * 2) + DllCall("Crypt32.dll\CryptBinaryToString", "ptr", InBin, "uint", InLen, "uint", Flags, "ptr", Out, "uint*", &OutLen) + return OutLen +} + +LC_Str2Bin(&Out, InSt, Flags) { + DllCall("Crypt32.dll\CryptStringToBinary", "ptr", InSt, "uint", StrLen(InSt), "uint", Flags, "ptr", 0, "uint*", &OutLen, "ptr", 0, "ptr", 0) + Out := Buffer(OutLen) + DllCall("Crypt32.dll\CryptStringToBinary", "ptr", InSt, "uint", StrLen(InSt), "uint", Flags, "ptr", Out, "uint*", &OutLen, "ptr", 0, "ptr", 0) + return OutLen +} + +; +; Version: 2014.03.06-1518, jNizM +; see https://en.wikipedia.org/wiki/Caesar_cipher +; =================================================================================== + +LC_Caesar(string, num := 2) { + ret := "" + loop parse string + { + c := Ord(A_LoopField) + if (c > 64) && (c < 91) + ret .= Chr(Mod(c - 65 + num, 26) + 65) + else if (c > 96) && (c < 123) + ret .= Chr(Mod(c - 97 + num, 26) + 97) + else + ret .= A_LoopField + } + return ret +} + +LC_CalcAddrHash(addr, length, algid, byref hash = 0, byref hashlength = 0) { + static h := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"] + static b := h.minIndex() + hProv := hHash := o := "" + if (DllCall("advapi32\CryptAcquireContext", "Ptr*", hProv, "Ptr", 0, "Ptr", 0, "UInt", 24, "UInt", 0xf0000000)) + { + if (DllCall("advapi32\CryptCreateHash", "Ptr", hProv, "UInt", algid, "UInt", 0, "UInt", 0, "Ptr*", hHash)) + { + if (DllCall("advapi32\CryptHashData", "Ptr", hHash, "Ptr", addr, "UInt", length, "UInt", 0)) + { + if (DllCall("advapi32\CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", 0, "UInt*", hashlength, "UInt", 0)) + { + VarSetCapacity(hash, hashlength, 0) + if (DllCall("advapi32\CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", &hash, "UInt*", hashlength, "UInt", 0)) + { + loop % hashlength + { + v := NumGet(hash, A_Index - 1, "UChar") + o .= h[(v >> 4) + b] h[(v & 0xf) + b] + } + } + } + } + DllCall("advapi32\CryptDestroyHash", "Ptr", hHash) + } + DllCall("advapi32\CryptReleaseContext", "Ptr", hProv, "UInt", 0) + } + return o +} +LC_CalcStringHash(string, algid, encoding = "UTF-8", byref hash = 0, byref hashlength = 0) { + chrlength := (encoding = "CP1200" || encoding = "UTF-16") ? 2 : 1 + length := (StrPut(string, encoding) - 1) * chrlength + VarSetCapacity(data, length, 0) + StrPut(string, &data, floor(length / chrlength), encoding) + return LC_CalcAddrHash(&data, length, algid, hash, hashlength) +} +LC_CalcHexHash(hexstring, algid) { + length := StrLen(hexstring) // 2 + VarSetCapacity(data, length, 0) + loop % length + { + NumPut("0x" SubStr(hexstring, 2 * A_Index - 1, 2), data, A_Index - 1, "Char") + } + return LC_CalcAddrHash(&data, length, algid) +} +LC_CalcFileHash(filename, algid, continue = 0, byref hash = 0, byref hashlength = 0) { + fpos := "" + if (!(f := FileOpen(filename, "r"))) + { + return + } + f.pos := 0 + if (!continue && f.length > 0x7fffffff) + { + return + } + if (!continue) + { + VarSetCapacity(data, f.length, 0) + f.rawRead(&data, f.length) + f.pos := oldpos + return LC_CalcAddrHash(&data, f.length, algid, hash, hashlength) + } + hashlength := 0 + while (f.pos < f.length) + { + readlength := (f.length - fpos > continue) ? continue : f.length - f.pos + VarSetCapacity(data, hashlength + readlength, 0) + DllCall("RtlMoveMemory", "Ptr", &data, "Ptr", &hash, "Ptr", hashlength) + f.rawRead(&data + hashlength, readlength) + h := LC_CalcAddrHash(&data, hashlength + readlength, algid, hash, hashlength) + } + return h +} + +LC_CRC32(string, encoding = "UTF-8") { + chrlength := (encoding = "CP1200" || encoding = "UTF-16") ? 2 : 1 + length := (StrPut(string, encoding) - 1) * chrlength + VarSetCapacity(data, length, 0) + StrPut(string, &data, floor(length / chrlength), encoding) + hMod := DllCall("Kernel32.dll\LoadLibrary", "Str", "Ntdll.dll") + SetFormat, Integer, % SubStr((A_FI := A_FormatInteger) "H", 0) + CRC32 := DllCall("Ntdll.dll\RtlComputeCrc32", "UInt", 0, "UInt", &data, "UInt", length, "UInt") + CRC := SubStr(CRC32 | 0x1000000000, -7) + DllCall("User32.dll\CharLower", "Str", CRC) + SetFormat, Integer, %A_FI% + return CRC, DllCall("Kernel32.dll\FreeLibrary", "Ptr", hMod) +} +LC_HexCRC32(hexstring) { + length := StrLen(hexstring) // 2 + VarSetCapacity(data, length, 0) + loop % length + { + NumPut("0x" SubStr(hexstring, 2 * A_Index -1, 2), data, A_Index - 1, "Char") + } + hMod := DllCall("Kernel32.dll\LoadLibrary", "Str", "Ntdll.dll") + SetFormat, Integer, % SubStr((A_FI := A_FormatInteger) "H", 0) + CRC32 := DllCall("Ntdll.dll\RtlComputeCrc32", "UInt", 0, "UInt", &data, "UInt", length, "UInt") + CRC := SubStr(CRC32 | 0x1000000000, -7) + DllCall("User32.dll\CharLower", "Str", CRC) + SetFormat, Integer, %A_FI% + return CRC, DllCall("Kernel32.dll\FreeLibrary", "Ptr", hMod) +} +LC_FileCRC32(sFile := "", cSz := 4) { + Bytes := "" + cSz := (cSz < 0 || cSz > 8) ? 2**22 : 2**(18 + cSz) + VarSetCapacity(Buffer, cSz, 0) + hFil := DllCall("Kernel32.dll\CreateFile", "Str", sFile, "UInt", 0x80000000, "UInt", 3, "Int", 0, "UInt", 3, "UInt", 0, "Int", 0, "UInt") + if (hFil < 1) + { + return hFil + } + hMod := DllCall("Kernel32.dll\LoadLibrary", "Str", "Ntdll.dll") + CRC32 := 0 + DllCall("Kernel32.dll\GetFileSizeEx", "UInt", hFil, "Int64", &Buffer), fSz := NumGet(Buffer, 0, "Int64") + loop % (fSz // cSz + !!Mod(fSz, cSz)) + { + DllCall("Kernel32.dll\ReadFile", "UInt", hFil, "Ptr", &Buffer, "UInt", cSz, "UInt*", Bytes, "UInt", 0) + CRC32 := DllCall("Ntdll.dll\RtlComputeCrc32", "UInt", CRC32, "UInt", &Buffer, "UInt", Bytes, "UInt") + } + DllCall("Kernel32.dll\CloseHandle", "Ptr", hFil) + SetFormat, Integer, % SubStr((A_FI := A_FormatInteger) "H", 0) + CRC32 := SubStr(CRC32 + 0x1000000000, -7) + DllCall("User32.dll\CharLower", "Str", CRC32) + SetFormat, Integer, %A_FI% + return CRC32, DllCall("Kernel32.dll\FreeLibrary", "Ptr", hMod) +} + +;from joedf : fork-fusion of jNizM+Laszlo's functions [to_decimal()+ToBase()] +LC_To_Dec(b, n) { ; 1 < b <= 36, n >= 0 + d:=0 + StringUpper,n,n + loop % StrLen(n) + { + d *= b, k:=SubStr(n,A_Index,1) + if k is not Integer + k:=Asc(k)-55 + d += k + } + return d +} +;from Laszlo : http://www.autohotkey.com/board/topic/15951-base-10-to-base-36-conversion/#entry103624 +LC_From_Dec(b,n) { ; 1 < b <= 36, n >= 0 + Loop { + d := mod(n,b), n //= b + m := (d < 10 ? d : Chr(d+55)) . m + IfLess n,1, Break + } + Return m +} +LC_Dec2Hex(x) { + return LC_From_Dec(16,x) +} +LC_Hex2Dec(x) { + return LC_To_Dec(16,x) +} +LC_Numvert(num,from,to) { ; from joedf : http://ahkscript.org/boards/viewtopic.php?f=6&t=6363 + return LC_From_Dec(to,LC_To_Dec(from,num)) +} + +; +; Date Updated: +; Friday, November 23rd, 2012 - Tuesday, February 10th, 2015 +; +; Script Function: +; Function Library to Encrypt / Decrypt in Div2 (by Joe DF) +; Div2 was invented with a friend for fun, back in ~2010. +; The string is "divided" in 2 during encryption. It is a +; simple reordering of the characters in a string. The was +; to have a human-readable/decryptable message. +; +; Notes: +; AutoTrim should turned off, for the encryption to work properly +; because, in Div2, and count as a character. +; + +LC_Div2_encode(input, WithAutoTrim:=1, numproc:=1) { + if (WithAutoTrim) + StringReplace,input,input,%A_Space%,_,A + loop, %numproc% + { + final:="", inputlen := StrLen(input) + divmax := ceil((0.5 * inputlen) + 1) + loop, %inputlen% + { + temp := SubStr(input,A_Index,1) + q := inputlen + 1 - A_Index + temp2 := SubStr(input,q,1) + if (A_Index < divmax) { + final .= temp + if (A_Index != q) + final .= temp2 + } + if (A_Index >= divmax) + Break + } + input := final + } + return final +} + +LC_Div2_decode(input, WithAutoTrim:=1, numproc:=1) { + if (WithAutoTrim) + StringReplace,input,input,%A_Space%,_,A + loop, %numproc% + { + i := 1, final:="", inputlen := StrLen(input) + loop, % loopc := ceil(inputlen * (1/2)) + { + if (i <= inputlen) + final .= SubStr(input,i,1) + i += 2 + } + i := inputlen + loop, %loopc% + { + if (i <= inputlen) { + if (mod(SubStr(i,0,1)+0,2)==1) { + if (i != 1) + final .= SubStr(input,i-1,1) + } else { + final .= SubStr(input,i,1) + } + } + i -= 2 + } + input := final + } + return final +} + + +LC_HMAC(Key, Message, Algo := "MD5") { + static Algorithms := {MD2: {ID: 0x8001, Size: 64} + , MD4: {ID: 0x8002, Size: 64} + , MD5: {ID: 0x8003, Size: 64} + , SHA: {ID: 0x8004, Size: 64} + , SHA256: {ID: 0x800C, Size: 64} + , SHA384: {ID: 0x800D, Size: 128} + , SHA512: {ID: 0x800E, Size: 128}} + static iconst := 0x36 + static oconst := 0x5C + if (!(Algorithms.HasKey(Algo))) + { + return "" + } + Hash := KeyHashLen := InnerHashLen := "" + HashLen := 0 + AlgID := Algorithms[Algo].ID + BlockSize := Algorithms[Algo].Size + MsgLen := StrPut(Message, "UTF-8") - 1 + KeyLen := StrPut(Key, "UTF-8") - 1 + VarSetCapacity(K, KeyLen + 1, 0) + StrPut(Key, &K, KeyLen, "UTF-8") + if (KeyLen > BlockSize) + { + LC_CalcAddrHash(&K, KeyLen, AlgID, KeyHash, KeyHashLen) + } + + VarSetCapacity(ipad, BlockSize + MsgLen, iconst) + Addr := KeyLen > BlockSize ? &KeyHash : &K + Length := KeyLen > BlockSize ? KeyHashLen : KeyLen + i := 0 + while (i < Length) + { + NumPut(NumGet(Addr + 0, i, "UChar") ^ iconst, ipad, i, "UChar") + i++ + } + if (MsgLen) + { + StrPut(Message, &ipad + BlockSize, MsgLen, "UTF-8") + } + LC_CalcAddrHash(&ipad, BlockSize + MsgLen, AlgID, InnerHash, InnerHashLen) + + VarSetCapacity(opad, BlockSize + InnerHashLen, oconst) + Addr := KeyLen > BlockSize ? &KeyHash : &K + Length := KeyLen > BlockSize ? KeyHashLen : KeyLen + i := 0 + while (i < Length) + { + NumPut(NumGet(Addr + 0, i, "UChar") ^ oconst, opad, i, "UChar") + i++ + } + Addr := &opad + BlockSize + i := 0 + while (i < InnerHashLen) + { + NumPut(NumGet(InnerHash, i, "UChar"), Addr + i, 0, "UChar") + i++ + } + return LC_CalcAddrHash(&opad, BlockSize + InnerHashLen, AlgID) +} + +/* from AHK forums +Fast 64- and 128-bit hash functions +Originally created by Laszlo , Jan 01 2007 06:59 PM + +https://autohotkey.com/board/topic/14040-fast-64-and-128-bit-hash-functions/ + +Here are two of hash functions, which +- are programmed fully in AHK +- are much faster than cryptographic hash functions +- provide long enough hash values (64 or 128 bits), so a collision is very unlikely + +They are modeled after Linear Feedback Shift Register (LFSR) based hash functions, like CRC-32. + +joedf: modified/updated for inclusion in libcrypt.ahk +The dynamic __LC_LHashTable global array variable is kept global in the interest of speed for successive calls. +*/ + +LC_L64Hash(x) { ; 64-bit generalized LFSR hash of string x + Local i, R = 0 + __LC_LHash_LHashInit() ; 1st time set LHASH0..LHAS256 global table + Loop Parse, x + { + i := (R >> 56) & 255 ; dynamic vars are global + R := (R << 8) + Asc(A_LoopField) ^ __LC_LHashTable%i% + } + Return __LC_LHash_Hex8(R>>32) . __LC_LHash_Hex8(R) +} + +LC_L128Hash(x) { ; 128-bit generalized LFSR hash of string x + Local i, S = 0, R = -1 + __LC_LHash_LHashInit() ; 1st time set LHASH0..LHAS256 global table + Loop Parse, x + { + i := (R >> 56) & 255 ; dynamic vars are global + R := (R << 8) + Asc(A_LoopField) ^ __LC_LHashTable%i% + i := (S >> 56) & 255 + S := (S << 8) + Asc(A_LoopField) - __LC_LHashTable%i% + } + Return __LC_LHash_Hex8(R>>32) . __LC_LHash_Hex8(R) . __LC_LHash_Hex8(S>>32) . __LC_LHash_Hex8(S) +} + +__LC_LHash_Hex8(i) { ; integer -> LS 8 hex digits + SetFormat Integer, Hex + i:= 0x100000000 | i & 0xFFFFFFFF ; mask LS word, set bit32 for leading 0's --> hex + SetFormat Integer, D + Return SubStr(i,-7) ; 8 LS digits = 32 unsigned bits +} + +__LC_LHash_LHashInit() { ; build pseudorandom substitution table + Local i, u = 0, v = 0 + If __LC_LHashTable0= + Loop 256 { + i := A_Index - 1 + __LC_LHASH_TEA(u,v, 1,22,333,4444, 8) ; <- to be portable, no Random() + __LC_LHashTable%i% := (u<<32) | v + } +} +; ; [y,z] = 64-bit I/0 block, [k0,k1,k2,k3] = 128-bit key +__LC_LHASH_TEA(ByRef y,ByRef z, k0,k1,k2,k3, n = 32) { ; n = #Rounds + s := 0, d := 0x9E3779B9 + Loop %n% { ; standard = 32, 8 for speed + k := "k" . s & 3 ; indexing the key + y := 0xFFFFFFFF & (y + ((z << 4 ^ z >> 5) + z ^ s + %k%)) + s := 0xFFFFFFFF & (s + d) ; simulate 32 bit operations + k := "k" . s >> 11 & 3 + z := 0xFFFFFFFF & (z + ((y << 4 ^ y >> 5) + y ^ s + %k%)) + } +} + +LC_MD2(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x8001, encoding) +} +LC_HexMD2(hexstring) { + return LC_CalcHexHash(hexstring, 0x8001) +} +LC_FileMD2(filename) { + return LC_CalcFileHash(filename, 0x8001, 64 * 1024) +} +LC_AddrMD2(addr, length) { + return LC_CalcAddrHash(addr, length, 0x8001) +} + +LC_MD4(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x8002, encoding) +} +LC_HexMD4(hexstring) { + return LC_CalcHexHash(hexstring, 0x8002) +} +LC_FileMD4(filename) { + return LC_CalcFileHash(filename, 0x8002, 64 * 1024) +} +LC_AddrMD4(addr, length) { + return LC_CalcAddrHash(addr, length, 0x8002) +} + +LC_MD5(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x8003, encoding) +} +LC_HexMD5(hexstring) { + return LC_CalcHexHash(hexstring, 0x8003) +} +LC_FileMD5(filename) { + return LC_CalcFileHash(filename, 0x8003, 64 * 1024) +} +LC_AddrMD5(addr, length) { + return LC_CalcAddrHash(addr, length, 0x8003) +} + +;nnnik's custom encryption algorithm +;Version 2.1 of the encryption/decryption functions + +LC_nnnik21_encryptStr(str="",pass="") +{ + If !(enclen:=(strput(str,"utf-16")*2)) + return "Error: Nothing to Encrypt" + If !(passlen:=strput(pass,"utf-8")-1) + return "Error: No Pass" + enclen:=Mod(enclen,4) ? (enclen) : (enclen-2) + Varsetcapacity(encbin,enclen,0) + StrPut(str,&encbin,enclen/2,"utf-16") + Varsetcapacity(passbin,passlen+=mod((4-mod(passlen,4)),4),0) + StrPut(pass,&passbin,strlen(pass),"utf-8") + LC_nnnik21_encryptbin(&encbin,enclen,&passbin,passlen) + LC_Base64_Encode(Text, encbin, enclen) + return Text +} + +LC_nnnik21_decryptStr(str="",pass="") +{ + If !((strput(str,"utf-16")*2)) + return "Error: Nothing to Decrypt" + If !((passlen:=strput(pass,"utf-8")-1)) + return "Error: No Pass" + Varsetcapacity(passbin,passlen+=mod((4-mod(passlen,4)),4),0) + StrPut(pass,&passbin,strlen(pass),"utf-8") + enclen:=LC_Base64_Decode(encbin, str) + LC_nnnik21__decryptbin(&encbin,enclen,&passbin,passlen) + return StrGet(&encbin,"utf-16") +} + + +LC_nnnik21_encryptbin(pBin1,sBin1,pBin2,sBin2) +{ + b:=0 + Loop % sBin1/4 + { + a:=numget(pBin1+0,sBin1-A_Index*4,"uint") + numput(a+b,pBin1+0,sBin1-A_Index*4,"uint") + b:=(a+b)*a + } + Loop % sBin2/4 + { + c:=numget(pBin2+0,(A_Index-1)*4,"uint") + b:=0 + Loop % sBin1/4 + { + a:=numget(pBin1+0,(A_Index-1)*4,"uint") + numput((a+b)^c,pBin1+0,(A_Index-1)*4,"uint") + b:=(a+b)*a + } + } +} + +LC_nnnik21__decryptbin(pBin1,sBin1,pBin2,sBin2){ + Loop % sBin2/4 + { + c:=numget(pBin2+0,sBin2-A_Index*4,"uint") + b:=0 + Loop % sBin1/4 + { + a:=numget(pBin1+0,(A_Index-1)*4,"uint") + numput(a:=(a^c)-b,pBin1+0,(A_Index-1)*4,"uint") + b:=(a+b)*a + } + } + b:=0 + Loop % sBin1/4 + { + a:=numget(pBin1+0,sBin1-A_Index*4,"uint") + numput(a:=a-b,pBin1+0,sBin1-A_Index*4,"uint") + b:=(a+b)*a + } +} + + +LC_RC4_Encrypt(Data,Pass) { + b:=0,j:=0,Key:=Object(),sBox:=Object() + VarSetCapacity(Result,StrLen(Data)*2) + Loop 256 + a:=(A_Index-1),Key[a]:=Asc(SubStr(Pass,Mod(a,StrLen(Pass))+1,1)),sBox[a]:=a + Loop 256 + a:=(A_Index-1),b:=(b+sBox[a]+Key[a])&255,sBox[a]:=(sBox[b]+0,sBox[b]:=sBox[a]) ; SWAP(a,b) + Loop Parse, Data + i:=(A_Index&255),j:=(sBox[i]+j)&255,k:=(sBox[i]+sBox[j])&255,sBox[i]:=(sBox[j]+0,sBox[j]:=sBox[i]) ; SWAP(i,j) + ,Result.=format("{:02x}", Asc(A_LoopField)^sBox[k]) + Return Result +} + +LC_RC4_Decrypt(Data,Pass) { + b:=0,j:=0,x:="0x",Key:=Object(),sBox:=Object() + VarSetCapacity(Result,StrLen(Data)//2) + Loop 256 + a:=(A_Index-1),Key[a]:=Asc(SubStr(Pass,Mod(a,StrLen(Pass))+1,1)),sBox[a]:=a + Loop 256 + a:=(A_Index-1),b:=(b+sBox[a]+Key[a])&255,sBox[a]:=(sBox[b]+0,sBox[b]:=sBox[a]) ; SWAP(a,b) + Loop % StrLen(Data)//2 + i:=(A_Index&255),j:=(sBox[i]+j)&255,k:=(sBox[i]+sBox[j])&255,sBox[i]:=(sBox[j]+0,sBox[j]:=sBox[i]) ; SWAP(i,j) + ,Result.=Chr((x . SubStr(Data,(2*A_Index)-1,2))^sBox[k]) + Return Result +} + +LC_RC4(RC4Data,RC4Pass) { ; Thanks Rajat for original, Updated Libcrypt version + ; http://www.autohotkey.com/board/topic/570-rc4-encryption/page-2#entry25712 + ATrim:=A_AutoTrim,BLines:=A_BatchLines,RC4PassLen:=StrLen(RC4Pass),Key:=Object(),sBox:=Object(),b:=0,RC4Result:="",i:=0,j:=0 + AutoTrim,Off + SetBatchlines,-1 + Loop, 256 + a:=(A_Index-1),ModVal:=Mod(a,RC4PassLen),c:=SubStr(RC4Pass,ModVal+=1,1),Key[a]:=Asc(c),sBox[a]:=a + Loop, 256 + a:=(A_Index-1),b:=Mod(b+sBox[a]+Key[a],256),T:=sBox[a],sBox[a]:=sBox[b],sBox[b]:=T + Loop, Parse, RC4Data + i:=Mod(i+1,256),j:=Mod(sBox[i]+j,256),k:=sBox[Mod(sBox[i]+sBox[j],256)],c:=Asc(A_LoopField)^k,c:=((c==0)?k:c),RC4Result.=Chr(c) + AutoTrim, %ATrim% + SetBatchlines, %BLines% + Return RC4Result +} + + +/* + - ROT5 covers the numbers 0-9. + - ROT13 covers the 26 upper and lower case letters of the Latin alphabet (A-Z, a-z). + - ROT18 is a combination of ROT5 and ROT13. + - ROT47 covers all printable ASCII characters, except empty spaces. Besides numbers and the letters of the Latin alphabet, + the following characters are included: + !"#$%&'()*+,-./:;<=>?[\]^_`{|}~ +*/ + +LC_Rot5(string) { + Loop, Parse, string + s .= (strlen((c:=A_LoopField)+0)?((c<5)?c+5:c-5):(c)) + Return s +} + +; by Raccoon July-2009 +; http://rosettacode.org/wiki/Rot-13#AutoHotkey +LC_Rot13(string) { + Loop, Parse, string + { + c := asc(A_LoopField) + if (c >= 97) && (c <= 109) || (c >= 65) && (c <= 77) + c += 13 + else if (c >= 110) && (c <= 122) || (c >= 78) && (c <= 90) + c -= 13 + s .= Chr(c) + } + Return s +} + +LC_Rot18(string) { + return LC_Rot13(LC_Rot5(string)) +} + +; adapted from http://langref.org/fantom+java+scala/strings/reversing-a-string/simple-substitution-cipher +; from decimal 33 '!' through 126 '~', 94 +LC_Rot47(string) { + Loop Parse, string + { + c := Asc(A_LoopField) + c += (c >= Asc("!") && c <= Asc("O") ? 47 : (c >= Asc("P") && c <= Asc("~") ? -47 : 0)) + s .= Chr(c) + } + Return s +} + +; RSHash (Robert Sedgewick's string hashing algorithm) +; from jNizM +; https://autohotkey.com/boards/viewtopic.php?p=87929#p87929 + +LC_RSHash(str) { + a := 0xF8C9, b := 0x5C6B7, h := 0 + loop, parse, str + h := h * a + Asc(A_LoopField), a *= b + return (h & 0x7FFFFFFF) +} + +LC_SecureSalted(salt, message, algo := "md5") { + hash := "" + saltedHash := LC_%algo%(message . salt) + saltedHashR := LC_%algo%(salt . message) + len := StrLen(saltedHash) + loop % len / 2 + { + byte1 := "0x" . SubStr(saltedHash, 2 * A_index - 1, 2) + byte2 := "0x" . SubStr(saltedHashR, 2 * A_index - 1, 2) + SetFormat, integer, hex + hash .= StrLen(ns := SubStr(byte1 ^ byte2, 3)) < 2 ? "0" ns : ns + } + SetFormat, integer, dez + return hash +} + +LC_SHA(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x8004, encoding) +} +LC_HexSHA(hexstring) { + return LC_CalcHexHash(hexstring, 0x8004) +} +LC_FileSHA(filename) { + return LC_CalcFileHash(filename, 0x8004, 64 * 1024) +} +LC_AddrSHA(addr, length) { + return LC_CalcAddrHash(addr, length, 0x8004) +} + +LC_SHA256(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x800c, encoding) +} +LC_HexSHA256(hexstring) { + return LC_CalcHexHash(hexstring, 0x800c) +} +LC_FileSHA256(filename) { + return LC_CalcFileHash(filename, 0x800c, 64 * 1024) +} +LC_AddrSHA256(addr, length) { + return LC_CalcAddrHash(addr, length, 0x800c) +} + +LC_SHA384(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x800d, encoding) +} +LC_HexSHA384(hexstring) { + return LC_CalcHexHash(hexstring, 0x800d) +} +LC_FileSHA384(filename) { + return LC_CalcFileHash(filename, 0x800d, 64 * 1024) +} +LC_AddrSHA384(addr, length) { + return LC_CalcAddrHash(addr, length, 0x800d) +} + +LC_SHA512(string, encoding = "UTF-8") { + return LC_CalcStringHash(string, 0x800e, encoding) +} +LC_HexSHA512(hexstring) { + return LC_CalcHexHash(hexstring, 0x800e) +} +LC_FileSHA512(filename) { + return LC_CalcFileHash(filename, 0x800e, 64 * 1024) +} +LC_AddrSHA512(addr, length) { + return LC_CalcAddrHash(addr, length, 0x800e) +} + +/* Written by Masonjar13 + + A static-class for a length-based rotational cipher. + + Works for any unicode string by first encoding the string + to base64. Decodes back to UTF-8 (could be altered to support + binary data). + + Methods & Parameters: +--------------- + LC_soupRot.enc() - encode string + str - string to encode + mult - rotation iteration count + junk - random character count to be added (default: 0) + + LC_soupRot.dec() - decode string + str - string to decode + mult - rotation iteration count used to encode + junk - random character count used to encode (default: 0) + + dependencies (can be found at https://github.com/Masonjar13/AHK-Library) + _randStr() + _rand() + _ifContains() + _isDigit() +--------------- + + Example: +------------ +iterationCnt:=a_tickCount +junk:=0 +str:="Hello° µWorld" + +encStr:=LC_soupRot.enc(str,iterationCnt,junk) +decStr:=LC_soupRot.dec(encStr,iterationCnt,junk) + +msgbox,,SoupRot,% "Original String: " str "`n`nEncrypted String: " encStr "`n`nDecrypted String: " decStr +------------ + +*/ + +class LC_soupRot { + enc(str,mult,junk:=0){ + str:=LC_Base64_EncodeText(str) + rotBase:=strLen(str) * mult + + for i,a in strSplit(str) { + + rot:=mod(rotBase*i,94) + nC:=asc(a)+rot + + while (nC > 126 || nC < 32) { + if (nC > 126) { + nC-=94 + } else if (nC < 32) { + nC+=94 + } + } + nStr.=chr(nC) + + if (junk) { + nStr.=soupRot.randStr(junk,junk,1234) + } + } + return nStr + } + dec(str,mult,junk:=0){ + i:=0 + rotBase:=strLen(str) * mult // (junk+1) + + for _,a in strSplit(str) { + if (skip) { + skip-- + continue + } + + rot:=mod(rotBase*++i,94) + nC:=asc(a)-rot + + while (nC > 126 || nC < 32) { + if (nC > 126) { + nC-=94 + } else if (nC < 32) { + nC+=94 + } + } + nStr.=chr(nC) + + if (junk) { + skip:=junk + } + } + return rTrim(LC_Base64_DecodeText(nStr),chr(65533)) ;"�" + } + + ; Dependencies + + _randStr(lowerBound,upperBound,mode:=1){ + if (!this._isDigit(lowerBound)||!this._isDigit(upperBound)||!this._isDigit(mode)) + return -1 + loop % this._rand(lowerBound,upperBound) { + t:="" + if (strLen(mode)=1) { + t:=mode + } else { + while (!this._ifContains(mode,t)) + t:=this._rand(1,4) + } + if (t=1) { + str.=chr(this._rand(97,122)) + } else if (t=2) { + str.=chr(this._rand(65,90)) + } else if (t=3) { + str.=this._rand(0,9) + } else if (t=4) { + i:=this._rand(1,4) + str.=i=1?chr(this._rand(33,47)):i=2?chr(this._rand(58,64)):i=3?chr(this._rand(91,96)):chr(this._rand(123,126)) + } + } + return str + } + _rand(lowerBound,upperBound){ + random,rand,% lowerBound,% upperBound + return rand + } + _ifContains(haystack,needle){ + if haystack contains %needle% + return 1 + } + _isDigit(in){ + if in is digit + return 1 + } +} + + +; analogous to encodeURIComponent() / decodeURIComponent() in javascript +; see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent + +; Modified by GeekDude from http://goo.gl/0a0iJq +LC_UriEncode(Uri, RE="[0-9A-Za-z]") { + VarSetCapacity(Var, StrPut(Uri, "UTF-8"), 0), StrPut(Uri, &Var, "UTF-8") + While Code := NumGet(Var, A_Index - 1, "UChar") + Res .= (Chr:=Chr(Code)) ~= RE ? Chr : Format("%{:02X}", Code) + Return, Res +} + +LC_UriDecode(Uri, Encoding:="UTF-8") { + Pos := 1 + While Pos := RegExMatch(Uri, "i)(%[\da-f]{2})+", Code, Pos) + { + VarSetCapacity(Var, StrLen(Code) // 3, 0), Code := SubStr(Code,2) + Loop, Parse, Code, `% + NumPut("0x" A_LoopField, Var, A_Index-1, "UChar") + Decoded := StrGet(&Var, Encoding) + Uri := SubStr(Uri, 1, Pos-1) . Decoded . SubStr(Uri, Pos+StrLen(Code)+1) + Pos += StrLen(Decoded)+1 + } + Return, Uri +} + +;---------------------------------- + +; analogous to encodeURI() / decodeURI() in javascript +; see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI + +LC_UrlEncode(Url) { + ; keep certain symbols like ":/;?@,&=+$#.", as per the standard js implementation + ; see https://github.com/ahkscript/libcrypt.ahk/issues/30 + return LC_UriEncode(Url, "[!#$&-;=?-Z_a-z~]") +} + +LC_UrlDecode(url) { + return LC_UriDecode(url) +} + +; +; Version: 2014.03.06-1518, jNizM +; see https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher +; =================================================================================== + +LC_VigenereCipher(string, key, enc := 1) { + enc := "", DllCall("user32.dll\CharUpper", "Ptr", &string, "Ptr") + , string := RegExReplace(StrGet(&string), "[^A-Z]") + loop, parse, string + { + a := Asc(A_LoopField) - 65 + , b := Asc(SubStr(key, 1 + Mod(A_Index - 1, StrLen(key)), 1)) - 65 + , enc .= Chr(Mod(a + b, 26) + 65) + } + return enc +} + +LC_VigenereDecipher(string, key) { + dec := "" + loop, parse, key + dec .= Chr(26 - (Asc(A_LoopField) - 65) + 65) + return LC_VigenereCipher(string, dec) +} + +; FUnctions and algorithm by VxE +; intergrated into libcrypt.ahk with "LC_" prefixes + +/* +#################################################################################################### +#################################################################################################### +###### ###### +###### [VxE]-251 Encryption ###### +###### & ###### +###### [VxE]-89 Encryption ###### +###### ###### +#################################################################################################### +#################################################################################################### + +[VxE] 251 encryption is a rotation-based encryption algorithm using a dynamic key and a +dynamic map. The '251' indicates the size of the map, which omits the following byte-values: +0x00 ( null byte: string terminator ) +0x09 ( tab character: common text formatting character ) +0x0A ( newline character: common text formatting character ) +0x0D ( carriage return character: common text formatting character ) +0x7F ( wierd character: ascii 'del' ) + +This encryption function also supports an 89-character map, which incorporates the byte values +between 0x20 and 0x7e, omitting 0x22, 0x27, 0x2C, 0x2F, 0x5C, and 0x60. This mode allows text value +input to be encrypted as text without high-ascii characters or non-printable characters. +*/ + +; ################################################################################################## +; ## Function shortcuts + +LC_VxE_Encrypt89( key, byref message ) { ; ---------------------------------------------------------- + Return LC_VxE_Crypt( key, message, 1, "vxe89 len" StrLen( message ) << !!A_IsUnicode ) +} ; VxE_Encrypt89( key, byref message ) ---------------------------------------------------------- + +LC_VxE_Decrypt89( key, byref message ) { ; ---------------------------------------------------------- + Return LC_VxE_Crypt( key, message, 0, "vxe89 len" StrLen( message ) << !!A_IsUnicode ) +} ; VxE_Decrypt89( key, byref message ) ---------------------------------------------------------- + +LC_VxE_Encrypt251( key, byref message, len ) { ; ---------------------------------------------------- + Return LC_VxE_Crypt( key, message, 1, "len" len ) +} ; VxE_Encrypt251( key, byref message, len ) ---------------------------------------------------- + +LC_VxE_Decrypt251( key, byref message, len ) { ; ---------------------------------------------------- + Return LC_VxE_Crypt( key, message, 0, "len" len ) +} ; VxE_Decrypt251( key, byref message, len ) ---------------------------------------------------- + +; ################################################################################################## +; ## The core function + +LC_VxE_Crypt( key, byref message, direction = 1, options="" ) { ; ----------------------------------- +; Transorms the message. 'direction' indicates whether or not to decrypt or encrypt the message. +; However, since this algorithm is symmetrical, distinguishing between 'encrypt' and 'decrypt' is +; merely for the benefit of human understanding. + +; This agorithm was developed by [VxE] in July 2010. When a key/message are passed to this function, +; it generates the rotation map using the key. Then, it traverses the bytes in the message, rotating +; their values along the map according to the key. Once the character's encoded value is determined, +; the key is augmented by a value based on the byte value. + + If !RegexMatch( options, "i)(?:len|l)\K(?:0x[\da-fA-F]+|\d+)", length ) ; check explicit length + length := StrLen( message ) << !!A_IsUnicode ; otherwise, find length. + UseVxE89 := InStr( options, "vxe89" ) ; check 'options' for text-friendly mode. + direction := 2 * ( direction = 1 ) - 1 ; coerce the 'direction' to either +1 or -1. + + w := StrLen( key ) << !!A_IsUnicode + ; 'w' holds the derived key, which is a 32-bit integer based on the key. + ; Although this doesn't seem very entropic, remember that the map is also derived from the key. + + If (UseVxE89) ; using the smaller map allows text-friendly encrypting since the small map is + Loop 126 ; composed only of low-ascii printable characters + If ( A_Index >= 32 && A_Index != 34 && A_Index != 39 && A_Index != 44 + && A_Index != 47 && A_Index != 92 && A_Index != 96 ) + map .= Chr( A_Index ) + If !UseVxE89 ; the 251 map is more suitable for non-text data + Loop 255 + If ( A_Index != 9 && A_Index != 10 && A_Index != 13 && A_Index != 127 ) + map .= Chr( A_Index ) + k := StrLen( map ) ; keep the length of the map + + Loop 9 ; pad the key up to 509 characters, mixing in digit-characters + If StrLen( key ) < 509 + key := SubStr( key Chr( 48 + A_Index ) key, 1, 509 ) + + Loop 509 ; rearrange the map, using the padded key as the selector. + { ; This is how the map becomes dynamic. 509 times, a char is selected from the map and + ; is extracted from the map string, then appended to it. At the same time, the derived key is + ; augmented by XORing it with a value based on each byte in the key. + q := *( &key + A_Index - 1 ) + pos := 1 + Mod( q * A_Index * 3, k ) + StringMid, e, map, %pos%, 1 + StringLeft, i, map, pos - 1 + StringTrimLeft, c, map, %pos% + map := i c e + w ^= q * A_Index * 1657 + } + x := 0 + Loop %length% + { + c := NumGet( message, A_Index - 1, "UChar" ) ; for each byte in the message + + If !c || !( i := InStr( map, Chr( c ), 1 ) ) + Continue ; if the character isn't in the map, just skip it. + i-- ; the map index should be zero based for easier use with Mod() function + x++ ; this tracks the actual index, not the char position. + + e := Mod( 223390000 + i + w * direction, k ) ; rotate the index along the map + + c := Asc( SubStr( map, e + 1, 1 ) ) ; lookup the character at the rotated index + + NumPut( c, message, A_Index - 1, "UChar" ) ; append the newly-mapped char to the result + + ; Finally, depending on the direction of rotation, use either the original index or + ; the rotated index to augment the derived key + If ( direction = 1 ) + c := Mod( e + x, 251 ) + Else c := Mod( i + x, 251 ) + w ^= c | c << 8 | c << 16 | c << 24 + } + return length +} ; VxE_Crypt( key, byref message, direction = 1, options="" ) ----------------------------------- + +LC_XOR_Encrypt(str,key) { + EncLen:=StrPut(Str,"UTF-16")*2 + VarSetCapacity(EncData,EncLen) + StrPut(Str,&EncData,"UTF-16") + + PassLen:=StrPut(key,"UTF-8") + VarSetCapacity(PassData,PassLen) + StrPut(key,&PassData,"UTF-8") + + LC_XOR(OutData,EncData,EncLen,PassData,PassLen) + LC_Base64_Encode(OutBase64, OutData, EncLen) + return OutBase64 +} + +LC_XOR_Decrypt(OutBase64,key) { + EncLen:=LC_Base64_Decode(OutData, OutBase64) + + PassLen:=StrPut(key,"UTF-8") + VarSetCapacity(PassData,PassLen) + StrPut(key,&PassData,"UTF-8") + + LC_XOR(EncData,OutData,EncLen,PassData,PassLen) + return StrGet(&EncData,"UTF-16") +} + +LC_XOR(byref OutData,byref EncData,EncLen,byref PassData,PassLen) +{ + VarSetCapacity(OutData,EncLen) + Loop % EncLen + NumPut(NumGet(EncData,A_Index-1,"UChar")^NumGet(PassData,Mod(A_Index-1,PassLen),"UChar"),OutData,A_Index-1,"UChar") +} \ No newline at end of file diff --git a/libcrypt/test_libcrypt_v2.ahk2 b/libcrypt/test_libcrypt_v2.ahk2 new file mode 100644 index 0000000..e61f49e --- /dev/null +++ b/libcrypt/test_libcrypt_v2.ahk2 @@ -0,0 +1,28 @@ +#Requires AutoHotkey v2.0 +#Include libcrypt_v2.ahk2 + +passed := 0, failed := 0, report := "" +Test(name, actual, expected) { + global passed, failed, report + if actual = expected + passed++, report .= "PASS " name "`n" + else + failed++, report .= "FAIL " name "`n expected: " expected "`n actual: " actual "`n" +} + +text := "Hello, Welt! 123 äöü" +Test("ASCII2Bin", LC_Bin2Ascii(LC_ASCII2Bin("ABC")), "ABC") +Test("BinStr UTF-8", LC_BinStr_DecodeText(LC_BinStr_EncodeText(text)), text) +Test("Base64 UTF-8", LC_Base64_DecodeText(LC_Base64_EncodeText(text)), text) +Test("ASCII85 original", LC_ASCII85_Decode(LC_ASCII85_Encode("Hello")), "Hello") +Test("ASCII85 Z85", LC_ASCII85_Decode(LC_ASCII85_Encode("test", "z"), "z"), "test") +Test("Caesar", LC_Caesar("Abc XyZ", 2), "Cde ZaB") +Test("ROT5", LC_Rot5("a1239"), "a6784") +Test("ROT13", LC_Rot13("Hello"), "Uryyb") +Test("ROT18", LC_Rot18("Hello 123"), "Uryyb 678") +Test("ROT47", LC_Rot47(LC_Rot47("Hello! 123")), "Hello! 123") +Test("URI", LC_UriDecode(LC_UriEncode("ä & x")), "ä & x") +Test("URL", LC_UrlDecode(LC_UrlEncode("https://example.com/a?x=ä")), "https://example.com/a?x=ä") +Test("Div2", LC_Div2_decode(LC_Div2_encode("abcdef", false), false), "abcdef") +MsgBox("Passed: " passed "`nFailed: " failed "`n`n" report, "libcrypt v2 tests") +ExitApp() diff --git a/test.ahk2 b/test.ahk2 new file mode 100644 index 0000000..b02f648 --- /dev/null +++ b/test.ahk2 @@ -0,0 +1,22 @@ +#Requires AutoHotkey v2 +;#Include .\libcrypt.ahk + + +message := "The quick brown fox jumps over the lazy dog" +salt := "key" + +LC_Bin2Ascii(Bin) { + Bin := RegExReplace(Bin, "[^10]") + Loop StrLen(Bin) / 8 { + Asc := 0 + for Bit in StrSplit(SubStr(Bin, (A_Index - 1) * 8 + 1, 8)) + Asc += Asc + Bit + Out .= Chr(Asc) + } + return Out +} + +tst := LC_Bin2Ascii("01100110") +MsgBox(tst) +;MsgBox("SHA256:`t`t" LC_SHA256(message) "`nSHA256 + Salt:`t" LC_SecureSalted(salt, message, "sha256") "`n`n") +