Home > front end >  encode string aes-128 ecb in golang and decrypt in js
encode string aes-128 ecb in golang and decrypt in js

Time:06-25

I am trying to encrypt string on golang server, i have a aes-128 encrypt util

func EncryptAES(key []byte, plaintext string) (string, error) {
    // create cipher
    c, err := aes.NewCipher(key)
    if err != nil {
        return "", err
    }

    // allocate space for ciphered data
    out := make([]byte, len(plaintext))

    for i := 1; i <= len(plaintext)/16; i   {
        tempBuf := make([]byte, 16)

        offset := (i - 1) * 16
        limit := offset   16
        // encrypt
        c.Encrypt(tempBuf, []byte(plaintext[offset:limit]))

        for j := 0; j < len(tempBuf); j   {
            out[offset j] = tempBuf[j]
        }
    }
    // return hex string
    return hex.EncodeToString(out), nil
}

and after that i am trying to do something like that

    hasher := sha256.New()
    hasher.Write([]byte(word))
    sha := hasher.Sum(nil)

    cypherText := word   userSessionKey

    for len([]byte(cypherText)) != 0 {
        cypherText  = "0"
    }

    sha128 := sha[:len(sha)/2]

    captchaKey, err := utils.EncryptAES([]byte(hex.EncodeToString(sha128)), cypherText)
    if err != nil {
        SendErrorResponse(ctx, fasthttp.StatusInternalServerError, []byte("error generating aes session key " err.Error()))
        return
    }

but for this key and ciphertext i am getting this error on encryption/decryption aes site enter image description here

js func for decoding not working too

async function decryptAES128(key, cipherText){
    let hash = CryptoJS.SHA256(key).toString();
    hash = hash.substring(0, hash.length/2);

    console.log(hash);
    console.log(cipherText)

    const bytes = await CryptoJS.AES.decrypt(CryptoJS.enc.Hex.parse(cipherText), CryptoJS.enc.Hex.parse(hash), { mode: CryptoJS.mode.ECB });

    return CryptoJS.enc.Utf8.stringify(bytes.words)
}

just prints nothing

CodePudding user response:

The Go code pads with 0x30 values if the size of the plaintext (cypherText, a misleading term by the way) is not an integer multiple of the blocksize (16 bytes for AES). As key the UTF-8 encoding of the hex encoding of the first 16 bytes of the SHA256 value of the password (word) is used. The ciphertext is hex encoded.

Decryption with the online tool fails because the online tool uses PKCS#7 padding and the ciphertext is Base64 decoded. For decryption to be possible, the default PKCS#7 padding must be disabled and the ciphertext must be hex decoded, see e.g. CyberChef.

Decryption with the JavaScript code fails because CryptoJS uses PKCS#7 padding by default, the key is hex decoded, and the ciphertext is not passed as CipherParams object. For decryption to be possible, the default PKCS#7 padding must be disabled, the key must be UTF-8 encoded, and the ciphertext must be passed as a CipherParams object:

var password = 'день';
var key = CryptoJS.SHA256(password).toString();
key = key.substring(0, key.length/2);

var ciphertext = '46ef70c1193fa29024595964a0eb0157c4e6602da6c1429f8a2b81146f79e798'
var decrypted = CryptoJS.AES.decrypt(
    {ciphertext: CryptoJS.enc.Hex.parse(ciphertext)}, // Fix 1: pass a CipherParams object
    CryptoJS.enc.Utf8.parse(key), // Fix2: UTF-8 encode the key
    { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding }); // Fix 3: disable padding
console.log(decrypted.toString(CryptoJS.enc.Utf8));
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

gives as decrypted, UTF-8 decoded data: деньBvFGlrXeWCnPTwFC00000000.


Security: ECB does not use an IV and is therefore insecure. Nowadays, authenticated encryption is applied (e.g. GCM), but at least a mode with an IV (e.g. CBC).
Furthermore, it is insecure to use a digest as key derivation function (KDF). There are dedicated functions for this (e.g. Argon2 or PBKDF2). Also, the byte string of the KDF should be used directly and not the UTF-8 encoding of the hex encoding, which reduces security.
The 0x30 padding applied is generally unreliable. More reliable is e.g. PKCS#7 padding.

  • Related