go与java互用的AES实现

终于实现了go与java互用的AES算法实现。基于go可以编译windows与linux下的命令行工具,十分方便。

  • Java源码
import java.security.GeneralSecurityException;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AES {

	public static byte[] encrypt(String key, byte[] origData) throws GeneralSecurityException {

		byte[] keyBytes = getKeyBytes(key);
		byte[] buf = new byte[16];
		System.arraycopy(keyBytes, 0, buf, 0, keyBytes.length > buf.length ? keyBytes.length : buf.length);
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(buf, "AES"), new IvParameterSpec(keyBytes));
		return cipher.doFinal(origData);

	}

	public static byte[] decrypt(String key, byte[] crypted) throws GeneralSecurityException {
		byte[] keyBytes = getKeyBytes(key);
		byte[] buf = new byte[16];
		System.arraycopy(keyBytes, 0, buf, 0, keyBytes.length > buf.length ? keyBytes.length : buf.length);
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(buf, "AES"), new IvParameterSpec(keyBytes));
		return cipher.doFinal(crypted);
	}

	private static byte[] getKeyBytes(String key) {
		byte[] bytes = key.getBytes();
		return bytes.length == 16 ? bytes : Arrays.copyOf(bytes, 16);
	}

	public static String encrypt(String key, String val) throws GeneralSecurityException {
		byte[] origData = val.getBytes();
		byte[] crypted = encrypt(key, origData);
		return Base64.Encoder.RFC4648_URLSAFE.encodeToString(crypted);
	}

	public static String decrypt(String key, String val) throws GeneralSecurityException {
		byte[] crypted = Base64.Decoder.RFC4648_URLSAFE.decode(val);
		byte[] origData = decrypt(key, crypted);
		return new String(origData);
	}

	/**
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {

		if (args.length != 3) {
			System.err.print("Usage: java AES (-e|-d) <key> <content>");
		}
		if ("-e".equals(args[0])) {
			System.out.println(encrypt(args[1], args[2]));
		} else if ("-d".equals(args[0])) {
			System.out.println(decrypt(args[1], args[2]));
		} else {
			System.err.print("Usage: java AES (-e|-d) <key> <content>");
		}
	}

}
  • Go源码
package main

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"os"
)

func getKeyBytes(key string) []byte {
	keyBytes := []byte(key)
	switch l := len(keyBytes); {
	case l < 16:
		keyBytes = append(keyBytes, make([]byte, 16-l)...)
	case l > 16:
		keyBytes = keyBytes[:16]
	}
	return keyBytes
}

func encrypt(key string, origData []byte) ([]byte, error) {
	keyBytes := getKeyBytes(key)
	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	origData = PKCS5Padding(origData, blockSize)
	blockMode := cipher.NewCBCEncrypter(block, keyBytes[:blockSize])
	crypted := make([]byte, len(origData))
	blockMode.CryptBlocks(crypted, origData)
	return crypted, nil
}

func decrpt(key string, crypted []byte) ([]byte, error) {
	keyBytes := getKeyBytes(key)
	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	blockMode := cipher.NewCBCDecrypter(block, keyBytes[:blockSize])
	origData := make([]byte, len(crypted))
	blockMode.CryptBlocks(origData, crypted)
	origData = PKCS5UnPadding(origData)
	return origData, 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 Encrypt(key string, val string) (string, error) {
	origData := []byte(val)
	crypted, err := encrypt(key, origData)
	if err != nil {
		return "", err
	}
	return base64.URLEncoding.EncodeToString(crypted), nil
}

func Decrypt(key string, val string) (string, error) {
	crypted, err := base64.URLEncoding.DecodeString(val)
	if err != nil {
		return "", err
	}
	origData, err := decrpt(key, crypted)
	if err != nil {
		return "", err
	}
	return string(origData), nil
}

func main() {

	argc := len(os.Args)
	if argc != 4 {
		os.Stdout.WriteString("usage: AES (-e|-d) <key> <content>")
		return
	}

	switch os.Args[1] {
	case "-e":
		ret, err := Encrypt(os.Args[2], os.Args[3])
		if err != nil {
			os.Stderr.WriteString(err.Error())
			os.Exit(1)
		}
		println(ret)
	case "-d":
		ret, err := Decrypt(os.Args[2], os.Args[3])
		if err != nil {
			os.Stderr.WriteString(err.Error())
			os.Exit(1)
		}
		println(ret)
	default:
		os.Stdout.WriteString("usage: AES (-e|-d) <key> <content>")
	}
}

使用go可以编译Windows与Linux下的可执行工具。

原文地址:https://www.cnblogs.com/zolo/p/5886368.html