[crypto/aes] How do I specify an initialization vector?

672 views
Skip to first unread message

Chetan Gowda

unread,
Nov 16, 2017, 3:21:51 AM11/16/17
to golang-nuts
Hello,
In Go's standard implementation of AES-256 GCM cipher, how do I specify an initialization vector while decrypting data? I would really appreciate if someone can provide me some pointers here.

More context:
I'm trying to decrypt ApplePay tokens. Apple requires the data to be decrypted using AES–256 GCM with an initialization vector of 16 null bytes and no authentication data (step-4 in https://developer.apple.com/library/content/documentation/PassKit/Reference/PaymentTokenJSON/PaymentTokenJSON.html)
  • For ECC (EC_v1), Decrypt the data key using AES–256 (id-aes256-GCM 2.16.840.1.101.3.4.1.46), with an initialization vector of 16 null bytes and no associated authentication data.

How do I do this using the standard crypto/aes library which doesn't take initialization vector as a param?
Below is my reference implementation (error checking ignored for brevity). This code fails with the error "cipher: message authentication failed".

symmetricKey := []byte("derived_symmetric_key_32chars_xx")
ciphertext := []byte("applepay_encrypted_data")

block
, _ := aes.NewCipher(symmetricKey)
aesgcm
, _ := cipher.NewGCM(block)
nonce
:= make([]byte, aesgcm.NonceSize())

plaintext
, err := aesgcm.Open(cipherText[:0], nonce, cipherText, nil)
if err != nil {
  panic
(err)
}

Chetan Gowda

unread,
Nov 16, 2017, 3:28:06 AM11/16/17
to golang-nuts
Python equivalent of this is

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import ciphers
...
mode
= ciphers.modes.GCM(b'\0' * 16, ciphertext[-16:], 16)
decryptor
= ciphers.Cipher(ciphers.algorithms.AES(symmetric_key), mode, backend=default_backend()).decryptor()
print decryptor.update(cipherdata[:-16]) + decryptor.finalize()


Basically, how do I do this in Go using std crypto library?

Conrado PLG

unread,
Nov 17, 2017, 6:38:43 AM11/17/17
to golang-nuts


On Thursday, November 16, 2017 at 6:21:51 AM UTC-2, Chetan Gowda wrote:
More context:
I'm trying to decrypt ApplePay tokens. Apple requires the data to be decrypted using AES–256 GCM with an initialization vector of 16 null bytes and no authentication data (step-4 in https://developer.apple.com/library/content/documentation/PassKit/Reference/PaymentTokenJSON/PaymentTokenJSON.html)
  • For ECC (EC_v1), Decrypt the data key using AES–256 (id-aes256-GCM 2.16.840.1.101.3.4.1.46), with an initialization vector of 16 null bytes and no associated authentication data.

How do I do this using the standard crypto/aes library which doesn't take initialization vector as a param?
Below is my reference implementation (error checking ignored for brevity). This code fails with the error "cipher: message authentication failed".



What they call "initialization vector", the Go documentation calls "nonce". So you need to use cipher.NewGCMWithNonceSize, passing 16 as size. Also change the nonce allocation to allocate 16 bytes instead of aesgcm.NonceSize() (which is 12).

(The Apple spec is strange in this aspect, the default nonce size is really 12)


Chetan Gowda

unread,
Nov 17, 2017, 10:24:42 AM11/17/17
to golang-nuts
Thank you, Conrado. That indeed fixed it.
Reply all
Reply to author
Forward
0 new messages