go與java互用的AES實現

終於實現了go與java互用的AES算法實現。基於go能夠編譯windows與linux下的命令行工具,十分方便。java

  • 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下的可執行工具。linux

相關文章
相關標籤/搜索