GO語言JAVA語言實現的AES/CFB/256位的加密解密例子
阿新 • • 發佈:2019-02-15
AES加密解密演算法裡面,最複雜的的就是CFB模式,因為CFB模式每次附加隨機一個IV,造成同樣的KEY,每次生成的加密串不一樣。解密的時候要用到這個IV,IV附加在了加密好的資料裡面,有的實現是把IV放資料的最後,有的是最面前,比如加密之後的資料是XXX, 則最終的資料是 16Bytes的IV+XXX或者是XXX+16Bytes的IV。
package main import ( "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
還有就是我用的祕鑰是256位的。
go語言直接是 32 個byte的字串, java需要把32個byte的字串轉化為16進位制的字串, 長度是64個bytes,程式碼會再把64個byte的字串轉化為32個byte的二進位制key,本質都是256位的祕鑰, 只不過方便人工檢視祕鑰而已。