Skip to content

Latest commit

 

History

History
149 lines (106 loc) · 4.24 KB

Compatibility.md

File metadata and controls

149 lines (106 loc) · 4.24 KB

Compatibility

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.

Node.js

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)

Python

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)

Rust

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.

Elixir

{: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)

PHP

$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";

Java

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);
    }
}