I am encrypting like:
plaintextstr := "0000000000000thankustackoverflow"
plaintext := []byte(plaintextstr)
key := []byte("abcdefghijklmnop")
block, _ := aes.NewCipher(key)
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
fmt.Printf("%x
", ciphertext)
and the output is:
00000000000000000000000000000000d77aa6646bb541808ed23c88d4b06d30f42b01d6e806a02b29086bc82892334f
but the output from another version of this code writen in PHP is:
d77aa6646bb541808ed23c88d4b06d30f42b01d6e806a02b29086bc82892334fbf21ea861abbc3d72e44731978bb76c2
Notice the 00000000000000000000000000000000 is the exact length of the missing data at the end. And it's 32, the size of the orig plaintextstr. Any idea how to left shift all that in golang and get the missing data?
PHP:
<?php
include('Crypt/AES.php');
$aes = new Crypt_AES();
$aes->setKey('abcdefghijklmnop');
echo bin2hex($aes->encrypt("0000000000000thankustackoverflow"));
https://github.com/andrewarrow/phpseclib1/blob/master/Crypt/AES.php https://github.com/andrewarrow/phpseclib1/blob/master/Crypt/Rijndael.php
Debug php output:
00000000000000000000000000000000 <--- IV
30303030303030303030303030746861 block 0
d77aa6646bb541808ed23c88d4b06d30 crypted 0
6e6b75737461636b6f766572666c6f77 block 16
f42b01d6e806a02b29086bc82892334f crypted 16
10101010101010101010101010101010 block 32
bf21ea861abbc3d72e44731978bb76c2 crypted 32
It is not a shifting problem, it is an output buffer size problem due to the prefixing of the iv to the encrypted data.
The IV is a block of nulls (0x00) since it is never set to a value. It is prepended to the encrypted data, that is common. A block of padding needs to be added since the input data is an exact multiple of the block size.
This the output buffer needs to be the size of the iv + the size of the data + the size of the padding block. (16 + 32 + 16 = 64)
Add another block size to the output buffer:
ciphertext := make([]byte, aes.BlockSize + len(plaintext) + aes.BlockSize)
The PHP version was encoding an extra 16 bytes of an "empty" string that was filled with 16s!
p1 := "0000000000000tha"
p2 := "nkustackoverflow"
p1b := []byte(p1)
p2b := []byte(p2)
p3b, _ := hex.DecodeString("10101010101010101010101010101010")
fmt.Println(p3b)
key := []byte("abcdefghijklmnop")
block, _ := aes.NewCipher(key)
ciphertext := make([]byte, aes.BlockSize+16)
iv := ciphertext[:aes.BlockSize]
mode := cipher.NewCBCEncrypter(block, iv)
i := 0
for {
if i == 0 {
mode.CryptBlocks(ciphertext[aes.BlockSize:], p1b)
} else if i == 1 {
mode.CryptBlocks(ciphertext[aes.BlockSize:], p2b)
} else if i == 2 {
mode.CryptBlocks(ciphertext[aes.BlockSize:], p3b)
}
fmt.Printf("%x
", ciphertext[16:])
i += 1
if i > 2 {
break
}
}
This code prints the identical
stuff in golang that php is.