I am trying to decrypt data with Swift CryptoKit that I have encrypted with php using openssl_encrypt()
chacha20-poly1305
. Encrypting works, but when decrypting I get the error: incorrectParameterSize
(Swift: error 1, line 10).
PHP encryption using openssl_encrypt:
<?php
$plaintext = "Hello World";
$key = base64_decode("O7IaTssF6RKgc84b8daAHojiveFY4vyQ4zKRZv3APKc=");
$nonce = base64_decode("MmTNTi+MmTNTi+fB");
$encrypted =
openssl_encrypt(
$plaintext,
'chacha20-poly1305',
$key,
0,
$nonce
);
echo $encrypted;
Swift decryption using CryptoKit
import CryptoKit
import Foundation
let encoded_data = "OG54KzRFKytSSmQ5d0M4PQ=="
let encoded_nonce = "MmTNTi+MmTNTi+fB"
let encoded_key = "O7IaTssF6RKgc84b8daAHojiveFY4vyQ4zKRZv3APKc="
let data = Data(base64Encoded: encoded_data)!
let nonce = Data(base64Encoded: encoded_nonce)!
let key = SymmetricKey(data: Data(base64Encoded: encoded_key)!)
do{
let box = try ChaChaPoly.SealedBox(combined: data.base64EncodedData())
do{
let decryptedData = try ChaChaPoly.open(box,using: key)
let decryptedString = String(decoding: decryptedData, as: UTF8.self)
print("Decrypted string: (decryptedString)")
}catch{
print("error 2: (error)")
}
}catch{
print("error 1: (error)")
}
I also tried using sodium_crypto_aead_chacha20poly1305_encrypt()
to encrypt, which resulted in the error "authenticationFailure" (Swift: error 2, line 12).
PHP encryption using sodium_crypto_aead_chacha20poly1305_encrypt:
<?php
$plaintext = "Hello World";
$key = base64_decode("O7IaTssF6RKgc84b8daAHojiveFY4vyQ4zKRZv3APKc=");
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES);
$encrypted = sodium_crypto_aead_chacha20poly1305_encrypt($plaintext,"",$nonce, $key);
echo "Data:" . base64_encode($encrypted) . "n";
echo "Nonce:" . base64_encode($nonce);
2
Answers
In a real-world scenario, you would need to validate the data, nonce, and key before attempting to decrypt the data to ensure that they have not been modified or corrupted.
ChaCha20-Poly1305 is authenticated encryption, i.e. during encryption a tag is generated in addition to the ciphertext, which is required for authentication during decryption.
The PHP/OpenSSL code does not generate this tag due to a bug, which is therefore missing when decrypting with the Swift code, so decryption fails (PHP/OpenSSL internally decryption works). More details about the bug are described in #76935.
PHP/Sodium, on the other hand, works:
The test data is from here, i.e. was generated with CryptoKit’s ChaCha20-Poly1305, so decryption with your Swift code should give the original plaintext (the key corresponds to the SHA256 hash of
password
).Note that
sodium_crypto_aead_chacha20poly1305_ietf_encrypt()
returns as result the concatenation of ciphertext and tag, so that$nonceCtTag
corresponds to thecombined
representation (nonce|ciphertext|tag) to be passed inSealedBox(combined: ...)
.The code above uses
sodium_crypto_aead_chacha20poly1305_ietf_encrypt()
with a 12 bytes nonce instead ofsodium_crypto_aead_chacha20poly1305_encrypt()
with an 8 bytes nonce (see here for more details regarding the different variants).