Dart: How to use the `AES-256-CBC` method in encrypt package? - php

My PHP server uses the encrypt as follows.
openssl_encrypt('data', 'AES-256-CBC', '1234567890123456', 0, '1234567890123456')
the result is adVh7c/vcyascTS0Z669IA==.
My dart server uses encrypt package as follows.
import 'package:encrypt/encrypt.dart' as encrypt;
Encrypter(AES(encryptKey, mode: AESMode.cbc)).encrypt('data', iv: '1234567890123456').base64
final encrypt.Key encryptKey = encrypt.Key.fromUtf8('1234567890123456');
final encrypt.IV encryptIvKey = encrypt.IV.fromUtf8('1234567890123456');
final encrypt.Encrypter encrypter = encrypt.Encrypter(encrypt.AES(encryptKey, mode: encrypt.AESMode.cbc));
print(encrypter.encrypt('data', iv: encryptIvKey).base64);
The result is KQjJ76efmVlgGKDsj6dCog==.
These result values are different.
I saw the cipher method of PHP. If I change the cipher method in the PHP server from
AES-256-CBC
to
aes-128-cbc // or aes-128-cbc-hmac-sha1, aes-128-cbc-hmac-sha256
The result will be KQjJ76efmVlgGKDsj6dCog==. (same as the result from the dart server)
But editing files in the PHP server is the last choice.
What I can do in the dart server to make the result the same as the result from the PHP server (AES-256-CBC method)?
How to use the AES-256-CBC method in encrypt package?
If I must edit files in the PHP server, what method I should use?
The aes-128-cbc, aes-128-cbc-hmac-sha1 and aes-128-cbc-hmac-sha256 give the same result. Or some method better than this and it is available in encrypt package as follows in this image. Suggestion me, please.

The summary from the comment in my post by #Topaco.
The aes-256-cbc cipher method requires a 32 bytes key.
Use the key with a string length of 32 or use the padRight(32, '\x00') function.
example:
final encrypt.Key encryptKey = encrypt.Key.fromUtf8('1234567890123456'.padRight(32, '\x00'));
Regarding aes-128-cbc, aes-128-cbc-hmac-sha1 and aes-128-cbc-hmac-sha256: Apply aes-128-cbc(ref)

Related

Encryption method that works both in ABAP and PHP?

Is there is any encryption function that work in SAP and PHP, of course except using BASE64 encode-decode method.
The scenario is
ABAP encrypt string with key.
The string send to PHP.
PHP decrypt the string using key.
Thank you very much for any advise.
Base64 doesn't an encryption method. #Dirk shared a blog post, which has information about cl_sec_sxml_writer class.
If your system hasn't got this class you can use AES library. It has more capable than cl_sec_sxml_writer class. You can use ECB, CBC, PCBC, CFB, OFB, CTR encryption modes and None, PKCS #5, PKCS #7 padding standarts.
Another option is using SSF_KRN_ENVELOPE function for encrypt. It use RSA standart so result may be huge for ofen trasfers. It is using server certificate for encryption, you an check certificate in STRUST t-code. You check SSF01 demo program.

Making RSA encryption compatible in Python (PyCrypto) and PHP (OpenSSL)

I am migrating an entire PHP API, and while I used PyCrypto before, I am not sure how to translate the following encryption call, since I need the exact same result. The PHP call is:
define('KEY', "-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC81t5iu5C0JxYq5/XNPiD5ol3Z
w8rw3LtFIUm7y3m8o8wv5qVnzGh6XwQ8LWypdkbBDKWZZrAUd3lybZOP7/82Nb1/
noYj8ixVRdbnYtbsSAbu9PxjB7a/7LCGKsugLkou74PJDadQweM88kzQOx/kzAyV
bS9gCCVUguHcq2vRRQIDAQAB
-----END PUBLIC KEY-----");
$cypher = "";
$result = openssl_public_encrypt($plain, $cypher, KEY, OPENSSL_PKCS1_PADDING);
echo bin2hex($cypher);
Assuming everything goes right, this prints the content from $cypher, passed to hexadecimal. For a sample input "azzzzzzzzzzzzdfdf" I get something like: "2281aeebc1166cdfb2f17a0a0775d927ca5a9ad999bae0e4954f58bd8082fdf7efe1fd284876530341f714456d7eb8cd44c57b20ab27029b84d5dc77a674bede3fe9065282931404286082e9df8607bdcff0818b90324dfee7d76b566d0f99bebc5cc913372c276ba373712128f1bcc226b59367cff93f7cdd6dbde25b366863".
I must assume this value as right, since the code was taken from an existing API I am migrating. However, trying the same with PyCrypto (yes, I am migrating the API to be available in Python), I use the following code:
def bin2hex(s):
return "".join([hex(ord(c))[2:].zfill(2) for c in s])
KEY = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC81t5iu5C0JxYq5/XNPiD5ol3Z
w8rw3LtFIUm7y3m8o8wv5qVnzGh6XwQ8LWypdkbBDKWZZrAUd3lybZOP7/82Nb1/
noYj8ixVRdbnYtbsSAbu9PxjB7a/7LCGKsugLkou74PJDadQweM88kzQOx/kzAyV
bS9gCCVUguHcq2vRRQIDAQAB
-----END PUBLIC KEY-----"""
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA
encrypter = PKCS1_v1_5.new(RSA.importKey(KEY))
print bin2hex(encrypter.encrypt("azzzzzzzzzzzzdfdf"));
While I expect the same value be returned and printed, the value finally is "3dd94ffabd01bb0e94010c0fedbcd4eb648f12e5d9e6d934b77ae86f76681d8a1b790cad9fddf6e6720415b4d645e525c33c402fa9778739b8e461790387e9508f7158a5fdc5723f5fc26d166b11a00759f0e0ee3ba6719a2e7c6b918f66e1311d1fff878ee2ca8762e1d6120f1e9585a76cdc7719ca20129ae76182b4277170".
Using PKCS1_OAEP outputs "290f60f37088c2cb46ae9221b01ff46a463f270ef7cf70bbea49de0b5ae43aec34a0eb46e694cf22f689eb77e808c590fdc30eda09f9d3f3cb8c15e0505bf5a984c2a121bc9fa83c6b5ccf50235f072467b4ae9cdf0f0ee2e486626ffa62ad1aa715fbe29e8afe4ceab3ca5a5df4c1dc75d7f258285d7ff1f4f2b4dcb7a8413a".
It is easy to tell that I must fix my python code. How can I fix my python code so it returns the exact same result as the given PHP call?
Your code is fine. PKCS#1 v1.5 padding in pyCrypto is randomized (source). So the encryption will always be different even if you use the same key and plaintext. This is a desirable property.
If you want to check compatibility between pyCrypto and PHP's OpenSSL extension, then you would need to encrypt in one, decrypt in the other and check that you got what you expected.
PKCS#1 v1.5 padding should not be used nowadays, because there are efficient attacks against it. OAEP is a much better alternative.
I've struggled with the same problem for quite long but finally managed to solve this.
The main issue was setting proper SHA hashes, in case of PHP's openssl_public_encrypt() it should be SHA1.
Here's the code for openssl_public_encrypt() with OPENSSL_PKCS1_OAEP_PADDING:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
def encrypt_key(message):
with open('public_key', 'rb') as key_file:
pub_key = key_file.read()
public_key = load_pem_public_key(pub_key, default_backend())
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
label=None
)
)
return ciphertext
basically a copy of cryptography.io documentation regarding RSA.

PHP CAST-256 mcrypt output differs

I am attempting to encrypt a string using CAST256 and CBC, via the PHP function mcrypt_encrypt. I am using the key test with the input test, which produces the following code:
mcrypt_encrypt(MCRYPT_CAST_256, 'test', 'test', MCRYPT_MODE_CBC);
The base64 encoded version of this produces (on PHP version 5.5.12):
DaypOCFVfoI8ghemj0ZkEg==
However, I am comparing my output against the tool on http://www.tools4noobs.com/online_tools/encrypt/, and my output differs significantly; the site output using the aforementioned cipher, mode, key, and data is the following:
eIKnQGAhjsGh+11XZsA2Lg==
Decrypting each string using the opposite tool (i.e. the site output decrypted with PHP, and the PHP output decrypted via the site) gives the following output:
DUCD000000000000 (site output)
DUCD000000000000 (PHP output)
However, decrypting using the same medium as the string was encrypted with gives the input data ('test').
My question is, is there a reason for this difference, such as omission of IV when encrypting/decrypting or a misuse of the PHP mcrypt_decrypt function?
This is most likely a bug in libmcrypt's cast-256 module, and the site that you've linked seems to be affected by it.
I get the same output as you do on your local machine and the RFC2612 test vectors also pass on mine, so don't worry - it's not a mistake on your part, nor is something broken on your end.
I do however have to say that you should never encrypt without using an IV and a proper encryption key ('test' is not a proper key). You should also use a more proven algorithm like AES.

AES-256-GCM mode decryption fails in php

Here's my code:
<?php
$secret="This is a secret message.";
$key="Secret key.";
$iv=openssl_random_pseudo_bytes(12);
$method="aes-256-gcm";
$encrypted=openssl_encrypt($secret,$method,$key,false,$iv);
$decrypted=openssl_decrypt($encrypted,$method,$key,false,$iv);
echo $encrypted;
echo "<br>";
echo $decrypted;
?>
I've got the encrypted message, but the decryption gives no result or error message.
The same code is working with another method, like aes-256-cbc.
Testing his out on my system (PHP 5.3.10 using return OpenSSL 1.0.1 internally) returns a ciphertext that has the same length as the plaintext (message).
This means that GCM encryption does not return the authentication tag, just the internal CTR mode encryption. This is likely because the PHP wrapper simply calls the OpenSSL interface directly and doesn't use the following code:
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
handleErrors();
which was found in the sample code of OpenSSL EVP ("higher level") encryption using GCM. In other words, the tag needs to be retrieved separately.
Handling the tag separately actually does make sense - it makes it possible to create a more online implementation that uses less buffering - but that doesn't help you here. You can use AES-CBC followed by a HMAC over the IV and ciphertext to replace GCM mode. Using a separate key for encryption and the authentication tag would make this scheme somewhat more secure.
PS you cannot directly use CTR mode decryption to retrieve the plaintext again because of differences in initialization.

IV too long in PHP mcrypt_generic_init

I am working on a project where all the data from the web services is being encrypted using Triple DES Encryption. In my specific case, I am receiving a query string from a URL that has been encrypted. The web service provider has given me two values for decryption: the encryption Key_192 and the initialization vector IV_192. Both these keys are 24 characters long.
When I attempt to decrypt the query string I have received in PHP, I am using the mcrypt library. When initializing the generic decrypt methods, part of my function is:
$key = "XXXXXXXXXXXXXXXXXXXXXXXX";
$iv = "YYYYYYYYYYYYYYYYYYYYYYYY";
$cipher = mcrypt_module_open(MCRYPT_3DES, '', 'cbc', '');
mcrypt_generic_init($cipher, $key, $iv);
$result = rtrim(mdecrypt_generic($cipher, $this->hex2bin($buffer)), "\0");
mcrypt_generic_deinit($cipher);
return $result;`
However, when I execute that portion of my code, I receive the following message:
mcrypt_generic_init(): Iv size incorrect; supplied length: 24, needed: 8
The web services provider was not able to provide any guidance on the error, instead directing me to their VB.NET implementation which has a line like:
Dim cs As CryptoStream = New CryptoStream(ms, cryptoProvider.CreateDecryptor(KEY_192, IV_192), CryptoStreamMode.Read)
where they pass the two keys in directly, similar to the mcrypt_generic_init() function.
I understand that the IV size is dependent upon the cypher method (Triple DES), but am confused as to why I have an IV longer than the function appears to support. How could that be? My experience with this kind of encryption is limited, and I have been unable to decrypt the query string into anything that doesn't look like a field of random characters.
Run mcrypt_enc_get_iv_size() to figure out the required IV size. For Triple DES, it will be 8. mcrypt_generic_init() requires a string of exactly the correct length, so you should use a shorter string (or, to do it on the fly, use substr()).
It turns out that my issue in decrypting was caused by differences in how the mcrypt PHP library and the VB.NET libraries pad strings while encrypting. Also, with regard to the original question, only the first 8 characters of the IV are actually used. The others are discarded. Better description is located here:
http://mishu666.wordpress.com/2007/08/20/problem-and-solve-of-3des-incompatibilities-with-nets-tripledescryptoserviceprovider/

Categories