Here’s how to decrypt in other languages.
Use the attribute key, not the master key. For files, skip Base64 decoding the ciphertext.
Pull requests are welcome for other languages.
const crypto = require('crypto')
let key = '61e6ba4a3a2498e3a8fdcd047eff0cd9864016f2c83c34599a3257a57ce6f7fb'
let ciphertext = 'Uv/+Sgar0kM216AvVlBH5Gt8vIwtQGfPysl539WY2DER62AoJg=='
key = Buffer.from(key, 'hex')
ciphertext = Buffer.from(ciphertext, 'base64') // skip for files
let nonce = ciphertext.slice(0, 12)
let auth_tag = ciphertext.slice(-16)
ciphertext = ciphertext.slice(12, -16)
let aesgcm = crypto.createDecipheriv('aes-256-gcm', key, nonce)
aesgcm.setAuthTag(auth_tag)
let plaintext = aesgcm.update(ciphertext) + aesgcm.final()
console.log(plaintext)
Install the cryptography package and use:
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from base64 import b64decode
key = '61e6ba4a3a2498e3a8fdcd047eff0cd9864016f2c83c34599a3257a57ce6f7fb'
ciphertext = 'Uv/+Sgar0kM216AvVlBH5Gt8vIwtQGfPysl539WY2DER62AoJg=='
key = bytes.fromhex(key)
ciphertext = b64decode(ciphertext) # skip for files
aesgcm = AESGCM(key)
plaintext = aesgcm.decrypt(ciphertext[:12], ciphertext[12:], b'')
print(plaintext)
Add crates:
[dependencies]
aes-gcm = "0.10.3"
base64 = "0.22.1"
hex = "0.4.3"
And use:
use aes_gcm::aead::{generic_array::GenericArray, Aead};
use aes_gcm::{Aes256Gcm, Key, KeyInit};
use base64::prelude::*;
fn main() {
let key = hex::decode("61e6ba4a3a2498e3a8fdcd047eff0cd9864016f2c83c34599a3257a57ce6f7fb").expect("decode failure!");
let ciphertext = BASE64_STANDARD.decode("Uv/+Sgar0kM216AvVlBH5Gt8vIwtQGfPysl539WY2DER62AoJg==").expect("decode failure!");
let key = Key::<Aes256Gcm>::from_slice(&key);
let aead = Aes256Gcm::new(key);
let nonce = GenericArray::from_slice(&ciphertext[..12]);
let plaintext_bytes = aead.decrypt(nonce, &ciphertext[12..]).expect("decryption failure!");
let plaintext = String::from_utf8(plaintext_bytes).expect("utf8 failure!");
println!("{:?}", plaintext);
}
Check out the aes-gcm docs for more on security and performance.
{:ok, key} = Base.decode16("61e6ba4a3a2498e3a8fdcd047eff0cd9864016f2c83c34599a3257a57ce6f7fb", case: :lower)
{:ok, ciphertext} = Base.decode64("Uv/+Sgar0kM216AvVlBH5Gt8vIwtQGfPysl539WY2DER62AoJg==")
data_size = byte_size(ciphertext) - 28
<<nonce::binary-size(12), data::binary-size(data_size), tag::binary>> = ciphertext
plaintext = :crypto.crypto_one_time_aead(:aes_256_gcm, key, nonce, data, "", tag, false)
IO.puts(plaintext)
$key = "61e6ba4a3a2498e3a8fdcd047eff0cd9864016f2c83c34599a3257a57ce6f7fb";
$ciphertext = "Uv/+Sgar0kM216AvVlBH5Gt8vIwtQGfPysl539WY2DER62AoJg==";
$key = hex2bin($key);
$ciphertext = base64_decode($ciphertext, true);
$nonce = substr($ciphertext, 0, 12);
$tag = substr($ciphertext, -16);
$ciphertext = substr($ciphertext, 12, -16);
$plaintext = openssl_decrypt($ciphertext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $nonce, $tag);
echo $plaintext . "\n";
import java.util.Base64;
import java.util.HexFormat;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Example
{
public static void main(String[] args) throws Exception {
String key = "61e6ba4a3a2498e3a8fdcd047eff0cd9864016f2c83c34599a3257a57ce6f7fb";
String ciphertext = "Uv/+Sgar0kM216AvVlBH5Gt8vIwtQGfPysl539WY2DER62AoJg==";
byte[] keyBytes = HexFormat.of().parseHex(key);
byte[] ciphertextBytes = Base64.getDecoder().decode(ciphertext);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, "AES"), new GCMParameterSpec(128, ciphertextBytes, 0, 12));
byte[] plaintextBytes = cipher.doFinal(ciphertextBytes, 12, ciphertextBytes.length - 12);
String plaintext = new String(plaintextBytes);
System.out.println(plaintext);
}
}