Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

163
Visualizações
What is the Python equivalent of this JS function to decrypt an AES-CCM-encrypted string?

I’d like to decrypt an AES-encrypted string (CCM mode) in Python 3.

The following JavaScript code which is using the sjcl library is working correctly:

const sjcl = require('sjcl');

const key = "ef530e1d82c154170296467bfe40cdb47b9ad77e685bbf8336b145dfa0e85640";
const keyArray = sjcl.codec.hex.toBits(key);
const iv = sjcl.codec.base64.fromBits(sjcl.codec.hex.toBits(key.substr(0,16))); 
const params = {
    "iv": iv,
    "v": 1,
    "iter": 1000,
    "ks": 256,
    "ts": 128,
    "mode": "ccm",
    "adata": "",
    "cipher": "aes",
    "salt": "",
};

function encrypt(data) {
    const ct = JSON.parse(sjcl.encrypt(keyArray, data, params)).ct;
    return sjcl.codec.hex.fromBits(sjcl.codec.base64.toBits(ct));
}

function decrypt(data) {
    const ct = sjcl.codec.base64.fromBits(sjcl.codec.hex.toBits(data));
    const paramsWithCt = JSON.stringify({ ...params, ...{ "ct": ct } });
    return sjcl.decrypt(keyArray, paramsWithCt);
}

let ct = encrypt("my secret string");
console.log("Cipher Text: " + ct);

let plain = decrypt(ct);
console.log("Plain Text: " + plain);

Output:

$ npm i sjcl
$ node index.js
Cipher Text: fa90bcdedbfe7ba89b69216e352a90fa57a63871fc4da7e69ab7f897f427f8e3
Plain Text: my secret string

Which library can I use to do the same in Python?

I tried using the pycryptodome library, but it accepts a different set of parameters:

  • key (bytes) – the cryptographic key
  • mode – the constant Crypto.Cipher.<algorithm>.MODE_CCM
  • nonce (bytes) – the value of the fixed nonce. It must be unique for the combination message/key. For AES, its length varies from 7 to 13 bytes. The longer the nonce, the smaller the allowed message size (with a nonce of 13 bytes, the message cannot exceed 64KB). If not present, the library creates a 11 bytes random nonce (the maximum message size is 8GB).
  • mac_len (integer) – the desired length of the MAC tag (default if not present: 16 bytes).
  • msg_len (integer) – pre-declaration of the length of the message to encipher. If not specified, encrypt() and decrypt() can only be called once.
  • assoc_len (integer) – pre-declaration of the length of the associated data. If not specified, some extra buffering will take place internally.
about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

The sjcl operates on arrays of 4 byte words. With sjcl.codec.hex.toBits() the hex encoded key is converted into such an array. The first 8 bytes (16 hexdigits) of the key are used as nonce.
Key size, tag size, algorithm and mode are determined from the params object. The params object further contains parameters for the key derivation, e.g. iter, salt, etc.), but these are ignored here since the key is passed as an array and not as a string.
Nonce and ciphertext are passed Base64 encoded within the params object.

The ciphertext is the concatenation of the actual ciphertext and the tag in this order, which must also be passed to the decryption in this format.
While the sjcl processes ciphertext and tag concatenated, PyCryptodome handles both separately. Apart from that, encryption and decryption in Python is straightforward with PyCryptodome:

from Crypto.Cipher import AES

data = b'my secret string'
key = bytes.fromhex('ef530e1d82c154170296467bfe40cdb47b9ad77e685bbf8336b145dfa0e85640')
nonce = bytes.fromhex('ef530e1d82c154170296467bfe40cdb47b9ad77e685bbf8336b145dfa0e85640')[:8]

# Encryption 
cipher = AES.new(key, AES.MODE_CCM, nonce)
ciphertext, tag = cipher.encrypt_and_digest(data)

ciphertextTagHex = ciphertext.hex() + tag.hex()
print(ciphertextTagHex) # fa90bcdedbfe7ba89b69216e352a90fa57a63871fc4da7e69ab7f897f427f8e3

# Decryption
ciphertextTag = bytes.fromhex(ciphertextTagHex)
ciphertext = ciphertextTag[:-16]
tag = ciphertextTag[-16:]

cipher = AES.new(key, AES.MODE_CCM, nonce)
try:
    decrypted = cipher.decrypt_and_verify(ciphertext, tag)
    print(decrypted.decode('utf-8')) # my secret string
except ValueError:
    print('Decryption failed')

Note that it is insecure to derive the nonce from the key. This is especially true for CCM, s. e.g. RFC4309, p. 3, last section:

AES CCM employs counter mode for encryption. As with any stream cipher, reuse of the same IV value with the same key is catastrophic.

Instead, the nonce should be randomly generated for each encryption. The nonce is not secret and is usually concatenated with the ciphertext at byte level, typically nonce|ciphertext|tag.

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda