Reputation: 670
I'm writing a Go script that will decrypt some legacy data that is encrypted with EVP_aes_256_cbc
and an RSA public key.
In C this would be something like:
key_size = EVP_OpenInit(&ctx, EVP_aes_256_cbc(), evp_key, eklen, iv, pkey);
//...
EVP_OpenUpdate(&ctx, destination, &len_out, buffer_in, buffer_size)
//...
EVP_OpenFinal(&ctx, destination+len_out, &len_out);
I have the evp_key
and iv
byte array equivalents in Go, but I must confess the order of how EVP works in OpenSSL eludes me (I'm fairly competent in C, but I can't get a grasp on the process by which this decryption happens from looking at the OpenSSL source.)
In Go, I can get this far:
pKey := //rsa.PrivateKey
eklen := 32
evpKey := "// hidden 32 byte array"
iv := "// hidden 16 byte array"
c, err := aes.NewCipher(iv)
cbc := cipher.NewCBCDecrypter(c, iv)
And here's where I get lost. I have an evpKey
and the pKey
, but I'm not sure how to decrypt the data from here. OpenSSL uses RSA_decrypt_old
or something like that, but I'm unable to track down what that actually means.
Is there a Go equivalent or do I need to bust out the much-too-expensive cgo
package and roll up my sleeves?
For anyone looking to replicate the EVP behavior in Go or just wondering how EVP works exactly, the following is breakdown. If you know the C (or Java or whatever OpenSSL implementation) was encrypting with something like:
// pseudo-code: don't copypasta and expect amazing
EVP_PKEY_assign_RSA(pkey, public_key);
EVP_CIPHER_CTX_init(&ctx);
EVP_SealInit(&ctx, EVP_aes_256_cbc(), &evp_key, &evp_key_len, iv, &pkey, 1);
EVP_SealUpdate(&ctx, buffer_out, &encrypt_len, (unsigned char*)buffer_in, len);
EVP_SealFinal(&ctx, buffer_out+encrypt_len, &encrypt_len);
The "Seal" actually just encrypts the key with the RSA public key.
In Go to decrypt something like that:
evpKeyBytes := "// the rsa.PublicKey encoded evpKey"
evpKey, err := rsa.DecryptPKCS1v15(rand.Reader, PrivateKeyRSA, evpKeyBytes)
c, err := aes.NewCipher(evpKey)
cbc := cipher.NewCBCDecrypter(c, iv)
decryptedDataBytes := make([]bytes, 2048) // some message size
cbc.CryptBlocks(decryptedDataBytes, encryptedDataBytes)
data = string(decryptedDataBytes)
// data should have the expected decrypted result.
Upvotes: 0
Views: 1673
Reputation: 99195
NewCipher
expects the key not the iv, and since you're passing it a 128bit iv it works as aes128cbc.
Upvotes: 2