Files
SamWaf/wafsec/cryptoutil.go
T

179 lines
3.8 KiB
Go

package wafsec
import (
"bytes"
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"os"
)
type CryptoUtil struct {
}
// 生成密钥对
func (r *CryptoUtil) CreateKeys(bits int) (prvkey, pubkey []byte) {
// 生成私钥文件
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
panic(err)
}
derStream := x509.MarshalPKCS1PrivateKey(privateKey)
block := &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: derStream,
}
prvkey = pem.EncodeToMemory(block)
publicKey := &privateKey.PublicKey
derPkix, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
panic(err)
}
block = &pem.Block{
Type: "PUBLIC KEY",
Bytes: derPkix,
}
pubkey = pem.EncodeToMemory(block)
return
}
// 公钥加密
func (r *CryptoUtil) RsaEncrypt(data, keyBytes []byte) ([]byte, error) {
//解密pem格式的公钥
block, _ := pem.Decode(keyBytes)
if block == nil {
panic(errors.New("public key error"))
}
// 解析公钥
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
panic(err)
}
// 类型断言
pub := pubInterface.(*rsa.PublicKey)
partLen := pub.N.BitLen()/8 - 11
chunks := split([]byte(data), partLen)
buffer := bytes.NewBufferString("")
//加密
for _, chunk := range chunks {
bytes, err := rsa.EncryptPKCS1v15(rand.Reader, pub, chunk)
if err != nil {
return nil, err
}
buffer.Write(bytes)
}
//加密
ciphertext := buffer.Bytes()
return ciphertext, nil
}
// 私钥解密
func (r *CryptoUtil) RsaDecrypt(ciphertext, keyBytes []byte) ([]byte, error) {
//获取私钥
block, _ := pem.Decode(keyBytes)
if block == nil {
panic(errors.New("private key error!"))
}
//解析PKCS1格式的私钥
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
panic(err)
}
partLen := priv.N.BitLen() / 8
chunks := split([]byte(ciphertext), partLen)
// 解密
buffer := bytes.NewBufferString("")
for _, chunk := range chunks {
decrypted, err := rsa.DecryptPKCS1v15(rand.Reader, priv, chunk)
if err != nil {
return nil, err
}
buffer.Write(decrypted)
}
return buffer.Bytes(), nil
}
// 签名
func (r *CryptoUtil) RsaSignWithSha256(data []byte, keyBytes []byte) ([]byte, error) {
h := sha256.New()
h.Write(data)
hashed := h.Sum(nil)
block, _ := pem.Decode(keyBytes)
if block == nil {
return nil, errors.New(fmt.Sprintf("private key error: "))
}
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, errors.New(fmt.Sprintf("ParsePKCS8PrivateKey: %s\n", err))
}
signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
if err != nil {
return nil, errors.New(fmt.Sprintf("Error from signing: %s\n", err))
}
return signature, nil
}
// 验证
func (r *CryptoUtil) RsaVerySignWithSha256(data, signData, keyBytes []byte) bool {
block, _ := pem.Decode(keyBytes)
if block == nil {
panic(errors.New("public key error"))
}
pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
panic(err)
}
hashed := sha256.Sum256(data)
err = rsa.VerifyPKCS1v15(pubKey.(*rsa.PublicKey), crypto.SHA256, hashed[:], signData)
if err != nil {
panic(err)
}
return true
}
func split(buf []byte, lim int) [][]byte {
var chunk []byte
chunks := make([][]byte, 0, len(buf)/lim+1)
for len(buf) >= lim {
chunk, buf = buf[:lim], buf[lim:]
chunks = append(chunks, chunk)
}
if len(buf) > 0 {
chunks = append(chunks, buf[:len(buf)])
}
return chunks
}
func (r *CryptoUtil) File2Bytes(filename string) ([]byte, error) {
// File
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
// FileInfo:
stats, err := file.Stat()
if err != nil {
return nil, err
}
// []byte
data := make([]byte, stats.Size())
count, err := file.Read(data)
if err != nil {
return nil, err
}
fmt.Printf("read file %s len: %d \n", filename, count)
return data, nil
}