AES加密解密算法里面,最复杂的的就是CFB模式,因为CFB模式每次附加随机一个IV,造成同样的KEY,每次生成的加密串不一样。解密的时候要用到这个IV,IV附加在了加密好的数据里面,有的实现是把IV放数据的最后,有的是最面前,比如加密之后的数据是XXX, 则最终的数据是 16Bytes的IV+XXX或者是XXX+16Bytes的IV。
package mainimport ( "crypto/aes" "crypto/cipher" "crypto/rand" "encoding/base64" "flag" "fmt" "io" "log" "os" "errors")var pass = flag.String("pass", "PassWord111111111111111111111111", "32 char password phrase- can be set to anything but keep it PRivate")var text = flag.String("text", "HelloWorld", "plain text to encode")var cipherText = flag.String("cipher", "", "cipher text")var verbose = flag.Bool("verbose", false, "verbose flag")func main() { flag.Parse() key := []byte(*pass) // 32 bytes if len(os.Args) < 2 { println("usage: goAES -pass Password111111111111111111111111 -text HelloWorld") println("or") println("usage: goAES -pass Password111111111111111111111111 -cipher HnOnMPZAb32fz1f80VIL2pjQ+ahp/upo") os.Exit(1) } data := "ILOVEYOUFOREVER" mystring := base64.StdEncoding.EncodeToString([]byte(data)) fmt.Printf("BASE64 = %s/n", mystring) if *cipherText == "" { plaintext := []byte(*text) ciphertextOutput, err := Actia_encrypt(key, plaintext) if err != nil { log.Fatal(err) } ciphertextOutput1, err := MIKE_encrypt(key, plaintext) fmt.Printf("Actia ENCRYTP = %s/n", ciphertextOutput) fmt.Printf("MIKE ENCRYTP = %s/n", ciphertextOutput1) } else { cipherBytes, err := base64.StdEncoding.DecodeString(*cipherText) if err != nil { log.Fatal("ERR=", err) } println("start DDecrypt") result, err := Actia_decrypt(key, cipherBytes) if err != nil { log.Fatal(err) } fmt.Printf("ACTIA_DECRYPT=%s/n", result) result1, err := MIKE_decrypt(key, cipherBytes) fmt.Printf("MIKE_DECRYPT=%s/n", result1) }}func Actia_encrypt(key, text []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } //b := base64.StdEncoding.EncodeToString(text) b := text ciphertext := make([]byte, aes.BlockSize+len(b)) if *verbose { println("blocksize=", aes.BlockSize, "ciphertext=", string(ciphertext)) } iv := ciphertext[:aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { return nil, err } cfb := cipher.NewCFBEncrypter(block, iv) cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b)) return []byte(base64.StdEncoding.EncodeToString(ciphertext)), nil //return ciphertext, nil}func Actia_decrypt(key, text []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } iv := text[:aes.BlockSize] text = text[aes.BlockSize:] if *verbose { println("iv", base64.StdEncoding.EncodeToString(iv), "cipher text", base64.StdEncoding.EncodeToString(iv)) } cfb := cipher.NewCFBDecrypter(block, []byte(iv)) cfb.XORKeyStream(text, text) //data, err := base64.StdEncoding.DecodeString(string(text)) //if err != nil { // return nil, err //} //str := string(text[:]) //fmt.Println(str) return text, nil}//-----------------------------------------------------------------------------------------//Here is our encrypt:func MIKE_encrypt(key, text []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } ciphertext := make([]byte, aes.BlockSize+len(text)) iv := ciphertext[:aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { return nil, err } cfb := cipher.NewCFBEncrypter(block, iv) cfb.XORKeyStream(ciphertext[aes.BlockSize:], text) return []byte(base64.StdEncoding.EncodeToString(ciphertext)), nil}//And this should be a working decrypt:func MIKE_decrypt(key, text []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } if len(text) < aes.BlockSize { return nil, errors.New("ciphertext too short") } iv := text[:aes.BlockSize] text = text[aes.BlockSize:] cfb := cipher.NewCFBDecrypter(block, iv) cfb.XORKeyStream(text, text) data, err := base64.StdEncoding.DecodeString(string(text)) if err != nil { return nil, err } return data, nil}用golang加密好之后, 用java解密,JAVA解密的代码在我上传的资源里有,我上传的资源里我自己修改过代码。JAVA源码在GitHub上的下载地址是:https://github.com/platinumjesus/crypto015,
需要下载和你jdk对应版本的 US_export_policy.jar和local_policy.jar 包, 替换你安装目录里的这两个包, 否则会有问题。
http://stackoverflow.com/questions/6481627/java-security-illegal-key-size-or-default-parameters
Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6
Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 7 Download
Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 8 Download
另外需要注意的就是 IV 的位置, 上面的go代码把IV放在前面, java代码放在了后面, 得修改了对应起来,否则go加密的数据java无法解密。还有就是我用的秘钥是256位的。
go语言直接是 32 个byte的字符串, java需要把32个byte的字符串转化为16进制的字符串, 长度是64个bytes,代码会再把64个byte的字符串转化为32个byte的二进制key,本质都是256位的秘钥, 只不过方便人工查看秘钥而已。
新闻热点
疑难解答