Java(Android)、Golang、Node.js三種語言AES加密互通


java(Android)版的AES加密
public String encryptWithAES(String key, String message) {
    try {
        // Use md5 value as the real key
        byte[] b = key.getBytes();
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] keyData = md.digest(b);

        SecretKeySpec skey = new SecretKeySpec(keyData), "AES");
        // Create an 8-byte initialization vector
        byte[] iv = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
                0x0e, 0x0f };
        AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
        
        Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        // CBC requires an initialization vector
        ecipher.init(Cipher.ENCRYPT_MODE, skey, paramSpec);

        byte[] plaintext = message.getBytes();
        byte[] result = ecipher.doFinal(plaintext, 0, plaintext.length);
        
        return Base64.encodeToString(result, Base64.DEFAULT);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

public String decryptWithAES(String key, String message) {
    try {
        // Use md5 value as the real key
        byte[] b = key.getBytes();
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] keyData = md.digest(b);

        SecretKeySpec skey = new SecretKeySpec(keyData), "AES");
        // Create an 8-byte initialization vector
        byte[] iv = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
                0x0e, 0x0f };
        AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
        
        Cipher dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        // CBC requires an initialization vector
        dcipher.init(Cipher.DECRYPT_MODE, skey, paramSpec);

        byte[] messageData = Base64.decode(message, Base64.DEFAULT);
        byte[] result = dcipher.doFinal(messageData, 0, messageData.length);
        
        return new String(result);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
Node.js版AES加密

let iv = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
    0x0e, 0x0f];

function encrypt_with_aes(key, message) {
    let md5 = crypto.createHash('md5').update(key).digest('hex');
    const cipher = crypto.createCipheriv(
        'aes-128-cbc',
        new Buffer(md5, 'hex'),
        new Buffer(iv)
    );
    // cipher.setAutoPadding(true);
    var encrypted = cipher.update(message, 'utf8', 'base64');
    encrypted += cipher.final('base64');
    console.log('encode message: ' + encrypted);
    return encrypted;
}

function decrypt_with_aes(key, message) {
    let md5 = crypto.createHash('md5').update(key).digest('hex');
    const decipher = crypto.createDecipheriv(
        'aes-128-cbc',
        new Buffer(md5, 'hex'),
        new Buffer(iv)
    );
    var decrypted = decipher.update(message, 'base64', 'utf8');
    decrypted += decipher.final('utf8');
    console.log('decode message: ' + decrypted);
    return decrypted;
}
Golang版AES加密
func EncryptWithAES(key, message string) string {

    hash := md5.New()
    hash.Write([]byte(key))
    keyData := hash.Sum(nil)

    block, err := aes.NewCipher(keyData)
    if err != nil {
        panic(err)
    }

    iv := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}

    enc := cipher.NewCBCEncrypter(block, iv)
    content := PKCS5Padding([]byte(message), block.BlockSize())
    crypted := make([]byte, len(content))
    enc.CryptBlocks(crypted, content)
    return base64.StdEncoding.EncodeToString(crypted)
}

func DecryptWithAES(key, message string) string {

    hash := md5.New()
    hash.Write([]byte(key))
    keyData := hash.Sum(nil)

    block, err := aes.NewCipher(keyData)
    if err != nil {
        panic(err)
    }

    iv := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
    
    messageData, _ := base64.StdEncoding.DecodeString(message)
    dec := cipher.NewCBCDecrypter(block, iv)
    decrypted := make([]byte, len(messageData))
    dec.CryptBlocks(decrypted, messageData)
    return string(PKCS5Unpadding(decrypted))
}

func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
    padding := blockSize - len(ciphertext)%blockSize
    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(ciphertext, padtext...)
}

func PKCS5Unpadding(encrypt []byte) []byte {
    padding := encrypt[len(encrypt)-1]
    return encrypt[:len(encrypt)-int(padding)]
}

Java版本和Node.js版本好久以前就已經(jīng)在用了,所以相互之間加解密肯定沒問題,但是這兩天在弄的這個Golang版本的死活就是不通,還以為是Padding的時候算法不一樣,后來幾乎把網(wǎng)絡上的Padding算法全部查遍了,都是一樣的,也就是說Padding肯定是不會錯的,最后一點點的排查才發(fā)現(xiàn)原來是key弄錯了,加密時key的長度沒有限制,但是AES128加密時key需要16位,所以這里就直接取key的MD5值,但是這個過程一不留心就出問題了。

MD5算法是這樣的

func Md5(buf []byte) string {
    hash := md5.New()
    hash.Write(buf)
    return fmt.Sprintf("%x", hash.Sum(nil))
}

在key生成MD5后直接輸出了hex后的字符串,然后對這個字符串直接轉[]byte

keyData := []byte(MD5([]byte(key)))

這樣就導致了key出錯,搞了一下午才查出問題所在,看來以后敲代碼還是得細心才行。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Node.js是目前非?;馃岬募夹g,但是它的誕生經(jīng)歷卻很奇特。 眾所周知,在Netscape設計出JavaScri...
    w_zhuan閱讀 3,732評論 2 41
  • Node.js是目前非?;馃岬募夹g,但是它的誕生經(jīng)歷卻很奇特。 眾所周知,在Netscape設計出JavaScri...
    Myselfyan閱讀 4,203評論 2 58
  • 數(shù)據(jù)傳輸加密 在開發(fā)應用過程中,客戶端與服務端經(jīng)常需要進行數(shù)據(jù)傳輸,涉及到重要隱私信息時,開發(fā)者自然會想到對其進行...
    chaychan閱讀 7,098評論 8 93
  • 印象中,她們?nèi)齻€都是靈巧的身形,但性格迥異。 王夢琪活潑開朗,張瑾萱則內(nèi)斂深沉。而夏菡,剛好處于她們中間,是那種溫...
    白羽君閱讀 495評論 0 0
  • 踩一腳海水 吹一陣海風 我在這里靜靜等候 愿與你相遇 生活在北京這樣的一線城市 走著走著 腳下的路就變得模糊了 也...
    吱音閱讀 269評論 0 0

友情鏈接更多精彩內(nèi)容