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做业务数据传输的加密。