RSA加解密
//生成密钥的时候随机数
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
publicKey := privateKey.PublicKey
//这里加入随机数,是为了进行混淆,保证同样的数据,两次加密的结果不一样。这个随机数和生成密钥的时候的随机数不一样
encryptedBytes, err := rsa.EncryptOAEP(
sha256.New(),
rand.Reader,
&publicKey,
[]byte("super secret message"),
nil)
if err != nil {
panic(err)
}
fmt.Println("encrypted bytes: ", encryptedBytes)
decryptedBytes, err := privateKey.Decrypt(nil, encryptedBytes, &rsa.OAEPOptions{Hash: crypto.SHA256})
if err != nil {
panic(err)
}
fmt.Println("decrypted message: ", string(decryptedBytes))
RSA进行签名
只有拥有私钥的人才能对信息进行签名,但是有公钥的人可以验证它。
msg := []byte("verifiable message")
msgHash := sha256.New()
_, err = msgHash.Write(msg)
if err != nil {
panic(err)
}
msgHashSum := msgHash.Sum(nil)
signature, err := rsa.SignPSS(rand.Reader, privateKey, crypto.SHA256, msgHashSum, nil)
if err != nil {
panic(err)
}
err = rsa.VerifyPSS(&publicKey, crypto.SHA256, msgHashSum, signature, nil)
if err != nil {
fmt.Println("could not verify signature: ", err)
return
}
fmt.Println("signature verified")
AES加解密和解密
使用golang实现AES算法很简单,系统库中已自带了CBC、CFB等等许多加密模式,而且可以很方便的设置IVPara,但是前几日在做AES加密时,发现传入的key必须是128bit、192bit或256bit,记得当时用Java实现的时候并没有这个问题。AES中的key的确是必须满足以上要求才行。这里就涉及到PKCS5Padding的
//加密数据
func (a *AesCryptor) Encrypt(data []byte) ([]byte, error) {
aesBlockEncrypter, err := aes.NewCipher(a.key)
content := PKCS5Padding(data, aesBlockEncrypter.BlockSize())
encrypted := make([]byte, len(content))
if err != nil {
println(err.Error())
return nil, err
}
aesEncrypter := cipher.NewCBCEncrypter(aesBlockEncrypter, a.iv)
aesEncrypter.CryptBlocks(encrypted, content)
return encrypted, nil
}
//解密数据
func (a *AesCryptor) Decrypt(src []byte) (data []byte, err error) {
decrypted := make([]byte, len(src))
var aesBlockDecrypter cipher.Block
aesBlockDecrypter, err = aes.NewCipher(a.key)
if err != nil {
println(err.Error())
return nil, err
}
aesDecrypter := cipher.NewCBCDecrypter(aesBlockDecrypter, a.iv)
aesDecrypter.CryptBlocks(decrypted, src)
return PKCS5Trimming(decrypted), nil
}
//PKCS5包装,如果刚好是16的倍数,就多填充一个block
func PKCS5Padding(cipherText []byte, blockSize int) []byte {
padding := blockSize - len(cipherText)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(cipherText, padText...)
}
//解包装
func PKCS5Trimming(encrypt []byte) []byte {
padding := encrypt[len(encrypt)-1]
return encrypt[:len(encrypt)-int(padding)]
}
总结
RSA保证安全,但是每次加密的数据长度有限制,数据较长需要做拆分,而且,非对称加密性能不好。
AES保证安全,每次数据加密的数据大小需要按照padding对齐,加密性能较好。CBC模式每次加密都依赖上一次加密的结果。
用RSA进行密钥交换,用AES做业务数据传输的加密。