終於實現了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>"); } } }
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