Go Nodejs Java Aes 128 CBC 加密解密结果保持一致

在多语言的生产环境下,常常是由一种语言进行加密而由另一种语言来进行解密,因此有必要保持各种语言之间加密解密算法的一致性。下面列出了Go,Nodejs,Java 的 Aes-128-Cbc的加密解密算法,它们的加解密结果是一致的。CBC比ECB加密强度更大,更难破解。

Go 1.15

package main

import (
        "bytes"
        "crypto/aes"
        "crypto/cipher"
        "encoding/hex"
        "fmt"
)

func AesEncryptCBC(origDataStr string, keystr string) string {
    
    
        origData := []byte(origDataStr)
        key := []byte(keystr)
        // 分组秘钥
        // NewCipher该函数限制了输入k的长度必须为16, 24或者32
        block, _ := aes.NewCipher(key)
        blockSize := block.BlockSize()                              // 获取秘钥块的长度
        origData = pkcs5Padding(origData, blockSize)                // 补全码
        blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) // 加密模式
        encrypted := make([]byte, len(origData))                    // 创建数组
        blockMode.CryptBlocks(encrypted, origData)                  // 加密
        return hex.EncodeToString(encrypted)
}
func AesDecryptCBC(ciphertext string, keystr string) (string, error) {
    
    
        encrypted, err := hex.DecodeString(ciphertext)
        if err != nil {
    
    
                return "", err
        }

        key := []byte(keystr)
        block, _ := aes.NewCipher(key)                              // 分组秘钥
        blockSize := block.BlockSize()                              // 获取秘钥块的长度
        blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) // 加密模式
        decrypted := make([]byte, len(encrypted))                   // 创建数组
        blockMode.CryptBlocks(decrypted, encrypted)                 // 解密
        decrypted = pkcs5UnPadding(decrypted)                       // 去除补全码
        return string(decrypted), nil
}
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(origData []byte) []byte {
    
    
        length := len(origData)
        unpadding := int(origData[length-1])
        return origData[:(length - unpadding)]
}

func main() {
    
    
        origData := "863861057163595" // 待加密的数据
        key := "sykKwe59_q11peDz" // 16字节加密的密钥

        fmt.Printf("原    文:%s\n", origData)
        encrypted := AesEncryptCBC(origData, key)
        fmt.Printf("加密结果:%s\n", encrypted)
        decrypted, err := AesDecryptCBC(encrypted, key)
        if err != nil {
    
    
                panic(err)
        }
        fmt.Printf("解密结果:%s\n", decrypted)
}

Nodejs 8.16

crypto = require("crypto");

aesEncrypt = function(plaintext, key) {
    
    
        var cip, encrypted;
        encrypted = '';
        cip = crypto.createCipheriv('aes-128-cbc', key, key);
        encrypted += cip.update(plaintext, 'binary', 'hex');
        encrypted += cip.final('hex');
        return encrypted;
};

aesDecrypt = function(encrypted, key) {
    
    
        var _decipher, decrypted, err;
        decrypted = '';
        _decipher = crypto.createDecipheriv('aes-128-cbc', key, key);
        decrypted += _decipher.update(encrypted, 'hex', 'binary');
        decrypted += _decipher.final('binary');
        return decrypted;
};

let key = "sykKwe59_q11peDz"
let plaintext = "863861057163595"

console.log("原    文:" + plaintext);
try {
    
    
        let encrypted = aesEncrypt(plaintext, key);
        console.log("加密结果:" + encrypted);
        console.log("解密结果:" + aesDecrypt(encrypted, key));
} catch(err) {
    
    
        console.log(err)
}

Java 1.8

package com.basic;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public class AesCbc {
    
    
	private static String parseByte2HexStr(byte buf[]) {
    
    
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < buf.length; i++) {
    
    
			String hex = Integer.toHexString(buf[i] & 0xFF);
			if (hex.length() == 1) {
    
    
				hex = '0' + hex;
			}
			sb.append(hex);
		}
		return sb.toString();
	}

	public static String encrypt(String value, String key) {
    
    
		try {
    
    
			IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
			SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
			cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
			// cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
			byte[] encrypted = cipher.doFinal(value.getBytes());
			return parseByte2HexStr(encrypted);
		} catch (Exception ex) {
    
    
			ex.printStackTrace();
		}
		return null;
	}

	private static byte[] toByte(String hexString) {
    
    
		int len = hexString.length() / 2;
		byte[] result = new byte[len];
		for (int i = 0; i < len; i++) {
    
    
			result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();
		}
		return result;
	}

	public static String decrypt(String encrypted, String key) {
    
    
		try {
    
    
			IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
			SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
			cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
			// cipher.init(Cipher.DECRYPT_MODE, skeySpec);
			byte[] original = cipher.doFinal(toByte(encrypted));

			return new String(original);
		} catch (Exception ex) {
    
    
			ex.printStackTrace();
		}

		return null;
	}

	public static void main(String[] args) {
    
    
		String key = "sykKwe59_q11peDz";
		String originalString = "863861057163595";
		System.out.println("原    文:" + originalString);
		String encryptedString = encrypt(originalString, key);
		System.out.println("加密结果:" + encryptedString);
		String decryptedString = decrypt(encryptedString, key);
		System.out.println("解密结果:" + decryptedString);
	}

}

输出:

原    文:863861057163595
加密结果:b95ba57ea11449c36e1d4130dade4efa
解密结果:863861057163595

相关文章:
《Go Nodejs Java Aes 128 ECB加密解密结果保持一致》

参考文章:
《nodejs和java的AES加密结果保持一致》
《golang的AES加密和解密的三种模式实现(CBC/ECB/CFB)》

猜你喜欢

转载自blog.csdn.net/pengpengzhou/article/details/119252686