elw
elw

Reputation: 13

Decrypting SubtleCrypto AES-GCM encoded string with Go

I'm trying to decrypt a string that was encrypted with SubtleCrypto AES-GCM in the browser (https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt). Using the following code in Javascript:


async function aesGcmEncrypt(plaintext, password) {
    const pwUtf8 = new TextEncoder().encode(password);                                 // encode password as UTF-8
    const pwHash = await crypto.subtle.digest('SHA-256', pwUtf8);                      // hash the password

    const iv = crypto.getRandomValues(new Uint8Array(12));                             // get 96-bit random iv
    const ivStr = Array.from(iv).map(b => String.fromCharCode(b)).join('');            // iv as utf-8 string

    const alg = { name: 'AES-GCM', iv: iv };                                           // specify algorithm to use

    const key = await crypto.subtle.importKey('raw', pwHash, alg, false, ['encrypt']); // generate key from pw

    const ptUint8 = new TextEncoder().encode(plaintext);                               // encode plaintext as UTF-8
    const ctBuffer = await crypto.subtle.encrypt(alg, key, ptUint8);                   // encrypt plaintext using key

    const ctArray = Array.from(new Uint8Array(ctBuffer));                              // ciphertext as byte array
    const ctStr = ctArray.map(byte => String.fromCharCode(byte)).join('');             // ciphertext as string

    return btoa(ivStr) + "." + btoa(ctStr);                                                             // iv+ciphertext base64-encoded
};


And im trying to decrypt the string in Go using:


func Decrypt(encryptedString string, keyString string) string {

    split := strings.Split(encryptedString, ".")

    key := []byte(keyString)
    enc, err := base64.StdEncoding.DecodeString(split[1])
    if err != nil {
        panic(err.Error())
    }
    nonce, err := base64.StdEncoding.DecodeString(split[0])
    if err != nil {
        panic(err.Error())
    }

    //Create a new Cipher Block from the key
    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err.Error())
    }

    //Create a new GCM
    aesGCM, err := cipher.NewGCM(block)
    if err != nil {
        panic(err.Error())
    }

    //Decrypt the data
    plaintext, err := aesGCM.Open(nil, nonce, enc, nil)
    if err != nil {
        panic(err.Error())
    }

    return string(plaintext)

}

However, every time I run into: "cipher: message authentication failed".

I guess there's something different with the implementations but I can't seem figure out what.

I tried using HEX instead of base64 (encoding and decoding) and tried using "cipher.NewGCMWithNonceSize()" instead of "cipher.NewGCM(block)".

Upvotes: 1

Views: 431

Answers (0)

Related Questions