加密解密在實際開發(fā)中應用比較廣泛,常用加解密分為:“對稱式”、“非對稱式”和”數(shù)字簽名“。對稱式:對稱加密(也叫私鑰加密)指加密和解密使用相同密鑰的加密算法。具體算法主要有DES算法,3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法。非對稱加密(公鑰加密):指加密和解密使用不同密鑰的加密算法,也稱為公私鑰加密。具體算法主要有RSA、Elgamal、背包算法、Rabin、D-H、ECC(橢圓曲線加密算法)。數(shù)字簽名:數(shù)字簽名是非對稱密鑰加密技術(shù)與數(shù)字摘要技術(shù)的應用。主要算法有md5、hmac、sha1等。以下介紹golang語言主要的加密解密算法實現(xiàn)。
md5
MD5信息摘要算法是一種被廣泛使用的密碼散列函數(shù),可以產(chǎn)生出一個128位(16進制,32個字符)的散列值(hash value),用于確保信息傳輸完整一致。
?
?
func?GetMd5String(s?string)?string?{ ????h?:=?md5.New() ????h.Write([]byte(s)) ????return?hex.EncodeToString(h.Sum(nil)) }
?
?
hmac
HMAC是密鑰相關(guān)的哈希運算消息認證碼(Hash-based Message Authentication Code)的縮寫, 它通過一個標準算法,在計算哈希的過程中,把key混入計算過程中。和自定義的加salt算法不同,Hmac算法針對所有哈希算法都通用,無論是MD5還是SHA-1。采用Hmac替代自己的salt算法,可以使程序算法更標準化,也更安全。示例
?
?
//key隨意設置?data?要加密數(shù)據(jù) func?Hmac(key,?data?string)?string?{ ????hash:=?hmac.New(md5.New,?[]byte(key))?//?創(chuàng)建對應的md5哈希加密算法 ????hash.Write([]byte(data)) ????return?hex.EncodeToString(hash.Sum([]byte(""))) } func?HmacSha256(key,?data?string)?string?{ ????hash:=?hmac.New(sha256.New,?[]byte(key))?//創(chuàng)建對應的sha256哈希加密算法 ????hash.Write([]byte(data)) ????return?hex.EncodeToString(hash.Sum([]byte(""))) }
?
?
sha1
SHA-1可以生成一個被稱為消息摘要的160位(20字節(jié))散列值,散列值通常的呈現(xiàn)形式為40個十六進制數(shù)。
?
?
func?Sha1(data?string)?string?{ ????sha1?:=?sha1.New() ????sha1.Write([]byte(data)) ????return?hex.EncodeToString(sha1.Sum([]byte(""))) }
?
?
AES
密碼學中的高級加密標準(Advanced Encryption Standard,AES),又稱Rijndael加密法,是美國聯(lián)邦政府采用的一種區(qū)塊加密標準。這個標準用來替代原先的DES(Data Encryption Standard),已經(jīng)被多方分析且廣為全世界所使用。AES中常見的有三種解決方案,分別為AES-128、AES-192和AES-256。如果采用真正的128位加密技術(shù)甚至256位加密技術(shù),蠻力攻擊要取得成功需要耗費相當長的時間。AES 有五種加密模式:
電碼本模式(Electronic Codebook Book (ECB))
密碼分組鏈接模式(Cipher Block Chaining (CBC))
計算器模式(Counter (CTR))
密碼反饋模式(Cipher FeedBack (CFB))
輸出反饋模式(Output FeedBack (OFB))
ECB模式
出于安全考慮,golang默認并不支持ECB模式。
?
?
package?main import?( ????"crypto/aes" ????"fmt" ) func?AESEncrypt(src?[]byte,?key?[]byte)?(encrypted?[]byte)?{ ????cipher,?_?:=?aes.NewCipher(generateKey(key)) ????length?:=?(len(src)?+?aes.BlockSize)?/?aes.BlockSize ????plain?:=?make([]byte,?length*aes.BlockSize) ????copy(plain,?src) ????pad?:=?byte(len(plain)?-?len(src)) ????for?i?:=?len(src);?i??0?{ ????????trim?=?len(decrypted)?-?int(decrypted[len(decrypted)-1]) ????} ????return?decrypted[:trim] } func?generateKey(key?[]byte)?(genKey?[]byte)?{ ????genKey?=?make([]byte,?16) ????copy(genKey,?key) ????for?i?:=?16;?i??
?
CBC模式
?
?
package?main import( ????"bytes" ????"crypto/aes" ????"fmt" ????"crypto/cipher" ????"encoding/base64" ) func?main()?{ ????orig?:=?"hello?world" ????key?:=?"0123456789012345" ????fmt.Println("原文:",?orig) ????encryptCode?:=?AesEncrypt(orig,?key) ????fmt.Println("密文:"?,?encryptCode) ????decryptCode?:=?AesDecrypt(encryptCode,?key) ????fmt.Println("解密結(jié)果:",?decryptCode) } func?AesEncrypt(orig?string,?key?string)?string?{ ????//?轉(zhuǎn)成字節(jié)數(shù)組 ????origData?:=?[]byte(orig) ????k?:=?[]byte(key) ????//?分組秘鑰 ????//?NewCipher該函數(shù)限制了輸入k的長度必須為16,?24或者32 ????block,?_?:=?aes.NewCipher(k) ????//?獲取秘鑰塊的長度 ????blockSize?:=?block.BlockSize() ????//?補全碼 ????origData?=?PKCS7Padding(origData,?blockSize) ????//?加密模式 ????blockMode?:=?cipher.NewCBCEncrypter(block,?k[:blockSize]) ????//?創(chuàng)建數(shù)組 ????cryted?:=?make([]byte,?len(origData)) ????//?加密 ????blockMode.CryptBlocks(cryted,?origData) ????return?base64.StdEncoding.EncodeToString(cryted) } func?AesDecrypt(cryted?string,?key?string)?string?{ ????//?轉(zhuǎn)成字節(jié)數(shù)組 ????crytedByte,?_?:=?base64.StdEncoding.DecodeString(cryted) ????k?:=?[]byte(key) ????//?分組秘鑰 ????block,?_?:=?aes.NewCipher(k) ????//?獲取秘鑰塊的長度 ????blockSize?:=?block.BlockSize() ????//?加密模式 ????blockMode?:=?cipher.NewCBCDecrypter(block,?k[:blockSize]) ????//?創(chuàng)建數(shù)組 ????orig?:=?make([]byte,?len(crytedByte)) ????//?解密 ????blockMode.CryptBlocks(orig,?crytedByte) ????//?去補全碼 ????orig?=?PKCS7UnPadding(orig) ????return?string(orig) } //補碼 //AES加密數(shù)據(jù)塊分組長度必須為128bit(byte[16]),密鑰長度可以是128bit(byte[16])、192bit(byte[24])、256bit(byte[32])中的任意一個。 func?PKCS7Padding(ciphertext?[]byte,?blocksize?int)?[]byte?{ ????padding?:=?blocksize?-?len(ciphertext)%blocksize ????padtext?:=?bytes.Repeat([]byte{byte(padding)},?padding) ????return?append(ciphertext,?padtext...) } //去碼 func?PKCS7UnPadding(origData?[]byte)?[]byte?{ ????length?:=?len(origData) ????unpadding?:=?int(origData[length-1]) ????return?origData[:(length?-?unpadding)] }?
?
CRT模式
?
?
package?main import?( ????"bytes" ????"crypto/aes" ????"crypto/cipher" ????"fmt" ) //加密 func?aesCtrCrypt(plainText?[]byte,?key?[]byte)?([]byte,?error)?{ ????//1.?創(chuàng)建cipher.Block接口 ????block,?err?:=?aes.NewCipher(key) ????if?err?!=?nil?{ ????????return?nil,?err ????} ????//2.?創(chuàng)建分組模式,在crypto/cipher包中 ????iv?:=?bytes.Repeat([]byte("1"),?block.BlockSize()) ????stream?:=?cipher.NewCTR(block,?iv) ????//3.?加密 ????dst?:=?make([]byte,?len(plainText)) ????stream.XORKeyStream(dst,?plainText) ????return?dst,?nil } func?main()?{ ????source:="hello?world" ????fmt.Println("原字符:",source) ????key:="1443flfsaWfdasds" ????encryptCode,_:=aesCtrCrypt([]byte(source),[]byte(key)) ????fmt.Println("密文:",string(encryptCode)) ????decryptCode,_:=aesCtrCrypt(encryptCode,[]byte(key)) ????fmt.Println("解密:",string(decryptCode)) }?
?
CFB模式
?
?
package?main import?( ????"crypto/aes" ????"crypto/cipher" ????"crypto/rand" ????"encoding/hex" ????"fmt" ????"io" ) func?AesEncryptCFB(origData?[]byte,?key?[]byte)?(encrypted?[]byte)?{ ????block,?err?:=?aes.NewCipher(key) ????if?err?!=?nil?{ ????????//panic(err) ????} ????encrypted?=?make([]byte,?aes.BlockSize+len(origData)) ????iv?:=?encrypted[:aes.BlockSize] ????if?_,?err?:=?io.ReadFull(rand.Reader,?iv);?err?!=?nil?{ ????????//panic(err) ????} ????stream?:=?cipher.NewCFBEncrypter(block,?iv) ????stream.XORKeyStream(encrypted[aes.BlockSize:],?origData) ????return?encrypted } func?AesDecryptCFB(encrypted?[]byte,?key?[]byte)?(decrypted?[]byte)?{ ????block,?_?:=?aes.NewCipher(key) ????if?len(encrypted)??
?
OFB模式
?
?
package?main import?( ????"bytes" ????"crypto/aes" ????"crypto/cipher" ????"crypto/rand" ????"encoding/hex" ????"fmt" ????"io" ) func?aesEncryptOFB(?data[]byte,key?[]byte)?([]byte,?error)?{ ????data?=?PKCS7Padding(data,?aes.BlockSize) ????block,?_?:=?aes.NewCipher([]byte(key)) ????out?:=?make([]byte,?aes.BlockSize?+?len(data)) ????iv?:=?out[:aes.BlockSize] ????if?_,?err?:=?io.ReadFull(rand.Reader,?iv);?err?!=?nil?{ ????????return?nil,?err ????} ????stream?:=?cipher.NewOFB(block,?iv) ????stream.XORKeyStream(out[aes.BlockSize:],?data) ????return?out,?nil } func?aesDecryptOFB(?data[]byte,key?[]byte)?([]byte,?error)?{ ????block,?_?:=?aes.NewCipher([]byte(key)) ????iv??:=?data[:aes.BlockSize] ????data?=?data[aes.BlockSize:] ????if?len(data)?%?aes.BlockSize?!=?0?{ ????????return?nil,?fmt.Errorf("data?is?not?a?multiple?of?the?block?size") ????} ????out?:=?make([]byte,?len(data)) ????mode?:=?cipher.NewOFB(block,?iv) ????mode.XORKeyStream(out,?data) ????out=?PKCS7UnPadding(out) ????return?out,?nil } //補碼 //AES加密數(shù)據(jù)塊分組長度必須為128bit(byte[16]),密鑰長度可以是128bit(byte[16])、192bit(byte[24])、256bit(byte[32])中的任意一個。 func?PKCS7Padding(ciphertext?[]byte,?blocksize?int)?[]byte?{ ????padding?:=?blocksize?-?len(ciphertext)%blocksize ????padtext?:=?bytes.Repeat([]byte{byte(padding)},?padding) ????return?append(ciphertext,?padtext...) } //去碼 func?PKCS7UnPadding(origData?[]byte)?[]byte?{ ????length?:=?len(origData) ????unpadding?:=?int(origData[length-1]) ????return?origData[:(length?-?unpadding)] } func?main()?{ ????source:="hello?world" ????fmt.Println("原字符:",source) ????key:="1111111111111111"http://16位??32位均可 ????encryptCode,_:=aesEncryptOFB([]byte(source),[]byte(key)) ????fmt.Println("密文:",hex.EncodeToString(encryptCode)) ????decryptCode,_:=aesDecryptOFB(encryptCode,[]byte(key)) ????fmt.Println("解密:",string(decryptCode)) }?
?
RSA加密
首先使用openssl生成公私鑰
?
?
package?main import?( ????"crypto/rand" ????"crypto/rsa" ????"crypto/x509" ????"encoding/base64" ????"encoding/pem" ????"errors" ????"fmt" ) //?私鑰生成 //openssl?genrsa?-out?rsa_private_key.pem?1024 var?privateKey?=?[]byte(` -----BEGIN?RSA?PRIVATE?KEY----- MIICWwIBAAKBgQDcGsUIIAINHfRTdMmgGwLrjzfMNSrtgIf4EGsNaYwmC1GjF/bM h0Mcm10oLhNrKNYCTTQVGGIxuc5heKd1gOzb7bdTnCDPPZ7oV7p1B9Pud+6zPaco qDz2M24vHFWYY2FbIIJh8fHhKcfXNXOLovdVBE7Zy682X1+R1lRK8D+vmQIDAQAB AoGAeWAZvz1HZExca5k/hpbeqV+0+VtobMgwMs96+U53BpO/VRzl8Cu3CpNyb7HY 64L9YQ+J5QgpPhqkgIO0dMu/0RIXsmhvr2gcxmKObcqT3JQ6S4rjHTln49I2sYTz 7JEH4TcplKjSjHyq5MhHfA+CV2/AB2BO6G8limu7SheXuvECQQDwOpZrZDeTOOBk z1vercawd+J9ll/FZYttnrWYTI1sSF1sNfZ7dUXPyYPQFZ0LQ1bhZGmWBZ6a6wd9 R+PKlmJvAkEA6o32c/WEXxW2zeh18sOO4wqUiBYq3L3hFObhcsUAY8jfykQefW8q yPuuL02jLIajFWd0itjvIrzWnVmoUuXydwJAXGLrvllIVkIlah+lATprkypH3Gyc YFnxCTNkOzIVoXMjGp6WMFylgIfLPZdSUiaPnxby1FNM7987fh7Lp/m12QJAK9iL 2JNtwkSR3p305oOuAz0oFORn8MnB+KFMRaMT9pNHWk0vke0lB1sc7ZTKyvkEJW0o eQgic9DvIYzwDUcU8wJAIkKROzuzLi9AvLnLUrSdI6998lmeYO9x7pwZPukz3era zncjRK3pbVkv0KrKfczuJiRlZ7dUzVO0b6QJr8TRAA== -----END?RSA?PRIVATE?KEY----- `) //?公鑰:?根據(jù)私鑰生成 //openssl?rsa?-in?rsa_private_key.pem?-pubout?-out?rsa_public_key.pem var?publicKey?=?[]byte(` -----BEGIN?PUBLIC?KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcGsUIIAINHfRTdMmgGwLrjzfM NSrtgIf4EGsNaYwmC1GjF/bMh0Mcm10oLhNrKNYCTTQVGGIxuc5heKd1gOzb7bdT nCDPPZ7oV7p1B9Pud+6zPacoqDz2M24vHFWYY2FbIIJh8fHhKcfXNXOLovdVBE7Z y682X1+R1lRK8D+vmQIDAQAB -----END?PUBLIC?KEY----- `) //?加密 func?RsaEncrypt(origData?[]byte)?([]byte,?error)?{ ????//解密pem格式的公鑰 ????block,?_?:=?pem.Decode(publicKey) ????if?block?==?nil?{ ????????return?nil,?errors.New("public?key?error") ????} ????//?解析公鑰 ????pubInterface,?err?:=?x509.ParsePKIXPublicKey(block.Bytes) ????if?err?!=?nil?{ ????????return?nil,?err ????} ????//?類型斷言 ????pub?:=?pubInterface.(*rsa.PublicKey) ????//加密 ????return?rsa.EncryptPKCS1v15(rand.Reader,?pub,?origData) } //?解密 func?RsaDecrypt(ciphertext?[]byte)?([]byte,?error)?{ ????//解密 ????block,?_?:=?pem.Decode(privateKey) ????if?block?==?nil?{ ????????return?nil,?errors.New("private?key?error!") ????} ????//解析PKCS1格式的私鑰 ????priv,?err?:=?x509.ParsePKCS1PrivateKey(block.Bytes) ????if?err?!=?nil?{ ????????return?nil,?err ????} ????//?解密 ????return?rsa.DecryptPKCS1v15(rand.Reader,?priv,?ciphertext) } func?main()?{ ????data,?_?:=?RsaEncrypt([]byte("hello?world")) ????fmt.Println(base64.StdEncoding.EncodeToString(data)) ????origData,?_?:=?RsaDecrypt(data) ????fmt.Println(string(origData)) } 編輯:黃飛?
評論
查看更多