前言
Golang比较强大,之前笔者在研究区块链的时间总结过加解密,这篇博文里的代码在其基础上进行了整理。笔者下面提供的代码是经过多语言环境验证,可以与其他语言互通。
- C#、Golang、Python、Java(Android)之间Des、Rsa加解密互通系列之前言
- C#、Golang、Python、Java(Android)之间Des、Rsa加解密互通系列之C#
- C#、Golang、Python、Java(Android)之间Des、Rsa加解密互通系列之Golang
- C#、Golang、Python、Java(Android)之间Des、Rsa加解密互通系列之Python
- C#、Golang、Python、Java(Android)之间Des、Rsa加解密互通系列之Java(Android)
代码
Des对称加密工具类
package sddes
import (
"bytes"
"crypto/cipher"
"crypto/des"
)
func Encrypt(origData, key []byte, iv []byte) ([]byte, error) {
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
origData = PKCS5Padding(origData, block.BlockSize())
// origData = ZeroPadding(origData, block.BlockSize())
blockMode := cipher.NewCBCEncrypter(block, iv)
crypted := make([]byte, len(origData))
// 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
// crypted := origData
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}
func Decrypt(crypted, key []byte, iv []byte) ([]byte, error) {
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
blockMode := cipher.NewCBCDecrypter(block, iv)
origData := make([]byte, len(crypted))
// origData := crypted
blockMode.CryptBlocks(origData, crypted)
origData = PKCS5UnPadding(origData)
// origData = ZeroUnPadding(origData)
return origData, nil
}
// 3DES加密
func TripleEncrypt(origData, key []byte, iv []byte) ([]byte, error) {
block, err := des.NewTripleDESCipher(key)
if err != nil {
return nil, err
}
origData = PKCS5Padding(origData, block.BlockSize())
blockMode := cipher.NewCBCEncrypter(block, iv)
crypted := make([]byte, len(origData))
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}
// 3DES解密
func TripleDecrypt(crypted, key []byte, iv []byte) ([]byte, error) {
block, err := des.NewTripleDESCipher(key)
if err != nil {
return nil, err
}
blockMode := cipher.NewCBCDecrypter(block, iv)
origData := make([]byte, len(crypted))
blockMode.CryptBlocks(origData, crypted)
origData = PKCS5UnPadding(origData)
return origData, nil
}
func ZeroPadding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{0}, padding)
return append(ciphertext, padtext...)
}
func ZeroUnPadding(origData []byte) []byte {
return bytes.TrimRightFunc(origData, func(r rune) bool {
return r == rune(0)
})
}
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
Rsa密钥对生成工具类
//生成公钥和私钥 pem文件
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/asn1"
"encoding/pem"
"flag"
"log"
"os"
)
func main() {
var bits int
flag.IntVar(&bits, "b", 1024, "秘钥长度,默认为1024")
if err := GenRsaKey(bits); err != nil {
log.Fatal("秘钥文件生成失败")
}
log.Println("秘钥文件生成成功")
}
//生成 PKCS1私钥、PKCS8私钥和公钥文件
func GenRsaKey(bits int) error {
//生成私钥文件
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return err
}
derStream := x509.MarshalPKCS1PrivateKey(privateKey)
block := &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: derStream,
}
file, err := os.Create("private_key.pem")
if err != nil {
return err
}
err = pem.Encode(file, block)
if err != nil {
return err
}
//生成PKCS8私钥
pk8Stream := MarshalPKCS8PrivateKey(derStream)
block = &pem.Block{
Type: "PRIVATE KEY",
Bytes: pk8Stream,
}
file, err = os.Create("pkcs8_private_key.pem")
if err != nil {
return err
}
err = pem.Encode(file, block)
if err != nil {
return err
}
//生成公钥文件
publicKey := &privateKey.PublicKey
defPkix, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return err
}
block = &pem.Block{
Type: "PUBLIC KEY",
Bytes: defPkix,
}
file, err = os.Create("public_key.pem")
if err != nil {
return err
}
err = pem.Encode(file, block)
if err != nil {
return err
}
return nil
}
// 由私钥获取PKCS8公钥 这种方式生成的PKCS8与OpenSSL转成的不一样,但是BouncyCastle里可用
func MarshalPKCS8PrivateKey(key []byte) []byte {
info := struct {
Version int
PrivateKeyAlgorithm []asn1.ObjectIdentifier
PrivateKey []byte
}{}
info.Version = 0
info.PrivateKeyAlgorithm = make([]asn1.ObjectIdentifier, 1)
info.PrivateKeyAlgorithm[0] = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
info.PrivateKey = key
k, err := asn1.Marshal(info)
if err != nil {
log.Panic(err.Error())
}
return k
}
// 由私钥获取PKCS8公钥
func MarshalPKCS8PrivateKey1(key *rsa.PrivateKey) []byte {
info := struct {
Version int
PrivateKeyAlgorithm []asn1.ObjectIdentifier
PrivateKey []byte
}{}
info.Version = 0
info.PrivateKeyAlgorithm = make([]asn1.ObjectIdentifier, 1)
info.PrivateKeyAlgorithm[0] = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
info.PrivateKey = x509.MarshalPKCS1PrivateKey(key)
k, err := asn1.Marshal(info)
if err != nil {
log.Panic(err.Error())
}
return k
}
Rsa加密、解密、签名、验签工具类
//公钥加密私钥解密 私钥签名公钥验证
package sdrsa
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"errors"
)
type PriKeyType uint
const (
PKCS1 PriKeyType = iota
PKCS8
)
//私钥签名
func Sign(data, privateKey []byte, keyType PriKeyType) ([]byte, error) {
h := sha256.New()
h.Write(data)
hashed := h.Sum(nil)
priv, err := getPriKey(privateKey, keyType)
if err != nil {
return nil, err
}
return rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA256, hashed)
}
//公钥验证
func SignVer(data, signature, publicKey []byte) error {
hashed := sha256.Sum256(data)
//获取公钥
pub, err := getPubKey(publicKey)
if err != nil {
return err
}
//验证签名
return rsa.VerifyPKCS1v15(pub, crypto.SHA256, hashed[:], signature)
}
// 公钥加密
func Encrypt(data, publicKey []byte) ([]byte, error) {
//获取公钥
pub, err := getPubKey(publicKey)
if err != nil {
return nil, err
}
//加密
return rsa.EncryptPKCS1v15(rand.Reader, pub, data)
}
// 私钥解密,privateKey为pem文件里的字符
func Decrypt(encData, privateKey []byte, keyType PriKeyType) ([]byte, error) {
//解析PKCS1a或者PKCS8格式的私钥
priv, err := getPriKey(privateKey, keyType)
if err != nil {
return nil, err
}
// 解密
return rsa.DecryptPKCS1v15(rand.Reader, priv, encData)
}
func getPubKey(publicKey []byte) (*rsa.PublicKey, 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
}
// 类型断言
if pub, ok := pubInterface.(*rsa.PublicKey); ok {
return pub, nil
} else {
return nil, errors.New("public key error")
}
}
func getPriKey(privateKey []byte, keyType PriKeyType) (*rsa.PrivateKey, error) {
//获取私钥
block, _ := pem.Decode(privateKey)
if block == nil {
return nil, errors.New("private key error!")
}
var priKey *rsa.PrivateKey
var err error
switch keyType {
case PKCS1:
{
priKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
}
case PKCS8:
{
prkI, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
priKey = prkI.(*rsa.PrivateKey)
}
default:
{
return nil, errors.New("unsupport private key type")
}
}
return priKey, nil
}