The key consists of five 32-bit numbers, stored in the variables k1...k5. If you have a text password you have to convert it to 5 numbers.
The password is not encrypted, but used to generate the key, which affects the encryption. The same password has to be given to decrypt the encrypted file. If a wrong one is given the decryption yields gibberish.
Below is a fully functional script. It encrypts a file using the password input by the user, and writes the encrypted file to disk. After that it decrypts this file with the same key – to see if everything works as expected. It was meant for demonstration of the concept, you have to ask the user, if encryption or decryption is needed, and perform only that action. The file names could be selected with FileSelectFile or some other nice GUI, it is up to you.
Code:
SetBatchLines -1
StringCaseSense Off
AutoTrim Off
InputBox pwd, PassPhrase, Enter your PassPhrase, HIDE, 400, 160
IfNotEqual ErrorLevel,0, ExitApp
PWD2Key(pwd, k1,k2,k3,k4,k5)
InputBox InpFile, Input, Enter the input file,, 400, 160,,,,,%A_ScriptFullPath%
IfNotEqual ErrorLevel,0, ExitApp
StringTrimRight File, InpFile, 4
InputBox EncFile, Encrypted file, Enter a name for the encrypted file,, 400, 160,,,,,%File%.enc
IfNotEqual ErrorLevel,0, ExitApp
InputBox DecFile, Decrypted file, Enter a name for the decrypted file,, 400, 160,,,,,%File%.dec
IfNotEqual ErrorLevel,0, ExitApp
ENCRYPT(EncFile,InpFile,k1,k2,k3,k4,k5) ; only one of it is needed at once
DECRYPT(DecFile,EncFile,k1,k2,k3,k4,k5)
ExitApp
PWD2Key(PW, ByRef k1, ByRef k2, ByRef k3, ByRef k4, ByRef k5)
{
CBC(k1,k2, PW, 1,2,3,4)
CBC(k3,k4, PW, 4,3,2,1)
k5 := k1^k2^k3^k4
}
CBC(ByRef u, ByRef v, x, k0,k1,k2,k3)
{
u = 0
v = 0
Loop % Ceil(StrLen(x)/8)
{
p = 0
StringLeft c, x, 4
Loop Parse, c
p := (p<<8) + Asc(A_LoopField)
u := u ^ p
p = 0
StringMid c, x, 5, 4
Loop Parse, c
p := (p<<8) + Asc(A_LoopField)
v := v ^ p
TEA(u,v,k0,k1,k2,k3)
StringTrimLeft x, x, 8
}
}
ENCRYPT(EncFile,InpFile,k1=0,k2=0,k3=0,k4=0,k5=0) ; encrypt InpFile to EncFile with key k1..k5
{
i = 9 ; pad-index, force restart
p = 0 ; counter to be encrypted
Loop Read, %InpFile%, %EncFile%
{
L = ; processed line
Loop % StrLen(A_LoopReadLine)
{
i++
IfGreater i,8, { ; all 9 pad values exhausted
u := p
v := k5 ; another secret
p++ ; increment counter
TEA(u,v, k1,k2,k3,k4)
Stream9(u,v) ; 9 pads from encrypted counter
i = 0
}
StringMid c, A_LoopReadLine, A_Index, 1
a := Asc(c)
if a between 32 and 126
{ ; chars > 126 or < 31 unchanged
a += s%i%
IfGreater a, 126, SetEnv, a, % a-95
c := Chr(a)
}
L = %L%%c% ; attach encrypted character
}
FileAppend %L%`n
}
}
DECRYPT(DecFile,EncFile,k1=0,k2=0,k3=0,k4=0,k5=0) ; decrypt EncFile to DecFile with key k1..k5
{
FileDelete %DecFile%
i = 9 ; pad-index, force restart
p = 0 ; counter to be encrypted
Loop Read, %EncFile%, %DecFile%
{
L = ; processed line
Loop % StrLen(A_LoopReadLine)
{
i++
IfGreater i,8, { ; all 9 pad values exhausted
u := p
v := k5 ; another secret
p++ ; increment counter
TEA(u,v, k1,k2,k3,k4)
Stream9(u,v) ; 9 pads from encrypted counter
i = 0
}
StringMid c, A_LoopReadLine, A_Index, 1
a := Asc(c)
if a between 32 and 126
{ ; chars > 126 or < 31 unchanged
a -= s%i%
IfLess a, 32, SetEnv, a, % a+95
c := Chr(a)
}
L = %L%%c% ; attach encrypted character
}
FileAppend %L%`n
}
}
TEA(ByRef y,ByRef z,k0,k1,k2,k3) ; (y,z) = 64-bit I/0 block
{ ; (k0,k1,k2,k3) = 128-bit key
IntFormat = %A_FormatInteger%
SetFormat Integer, D ; needed for decimal indices
s := 0
d := 0x9E3779B9
Loop 32
{
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%))
}
SetFormat Integer, %IntFormat%
y += 0
z += 0 ; Convert to original ineger format
}
Stream9(x,y) ; Convert 2 32-bit words to 9 pad values
{ ; 0 <= s0, s1, ... s8 <= 94
Local z ; makes all s%i% global
s0 := Floor(x*0.000000022118911147) ; 95/2**32
Loop 8
{
z := (y << 25) + (x >> 7) & 0xFFFFFFFF
y := (x << 25) + (y >> 7) & 0xFFFFFFFF
x = %z%
s%A_Index% := Floor(x*0.000000022118911147)
}
}
Edit: fixed CBC (ceil instead of floor, shorter code)