272 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			272 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package starcrypto
 | ||
| 
 | ||
| import (
 | ||
| 	"crypto"
 | ||
| 	"crypto/rand"
 | ||
| 	"crypto/rsa"
 | ||
| 	"crypto/x509"
 | ||
| 	"encoding/pem"
 | ||
| 	"errors"
 | ||
| 	"fmt"
 | ||
| 	"golang.org/x/crypto/ssh"
 | ||
| 	"math/big"
 | ||
| )
 | ||
| 
 | ||
| func GenerateKey(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) {
 | ||
| 	private, err := rsa.GenerateKey(rand.Reader, bits)
 | ||
| 	if err != nil {
 | ||
| 		return nil, nil, err
 | ||
| 	}
 | ||
| 	return private, &private.PublicKey, nil
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| func EncodePrivateKey(private *rsa.PrivateKey) []byte {
 | ||
| 	return pem.EncodeToMemory(&pem.Block{
 | ||
| 		Bytes: x509.MarshalPKCS1PrivateKey(private),
 | ||
| 		Type:  "RSA PRIVATE KEY",
 | ||
| 	})
 | ||
| }
 | ||
| 
 | ||
| func EncodePublicKey(public *rsa.PublicKey) ([]byte, error) {
 | ||
| 	publicBytes, err := x509.MarshalPKIXPublicKey(public)
 | ||
| 	if err != nil {
 | ||
| 		return nil, err
 | ||
| 	}
 | ||
| 	return pem.EncodeToMemory(&pem.Block{
 | ||
| 		Bytes: publicBytes,
 | ||
| 		Type:  "PUBLIC KEY",
 | ||
| 	}), nil
 | ||
| }
 | ||
| 
 | ||
| func DecodePrivateKey(private []byte, password string) (*rsa.PrivateKey, error) {
 | ||
| 	var prikey *rsa.PrivateKey
 | ||
| 	var err error
 | ||
| 	var bytes []byte
 | ||
| 	blk, _ := pem.Decode(private)
 | ||
| 	if blk == nil {
 | ||
| 		return nil, errors.New("private key error!")
 | ||
| 	}
 | ||
| 	if password != "" {
 | ||
| 		tmp, err := x509.DecryptPEMBlock(blk, []byte(password))
 | ||
| 		if err != nil {
 | ||
| 			return nil, err
 | ||
| 		}
 | ||
| 		bytes = tmp
 | ||
| 	} else {
 | ||
| 		bytes = blk.Bytes
 | ||
| 	}
 | ||
| 	prikey, err = x509.ParsePKCS1PrivateKey(bytes)
 | ||
| 	if err != nil {
 | ||
| 		tmp, err := x509.ParsePKCS8PrivateKey(bytes)
 | ||
| 		if err != nil {
 | ||
| 			return nil, err
 | ||
| 		}
 | ||
| 		prikey = tmp.(*rsa.PrivateKey)
 | ||
| 	}
 | ||
| 	return prikey, err
 | ||
| }
 | ||
| 
 | ||
| func DecodePublicKey(pubStr []byte) (*rsa.PublicKey, error) {
 | ||
| 	blk, _ := pem.Decode(pubStr)
 | ||
| 	if blk == nil {
 | ||
| 		return nil, errors.New("public key error")
 | ||
| 	}
 | ||
| 	pub, err := x509.ParsePKIXPublicKey(blk.Bytes)
 | ||
| 	if err != nil {
 | ||
| 		return nil, err
 | ||
| 	}
 | ||
| 	return pub.(*rsa.PublicKey), nil
 | ||
| }
 | ||
| 
 | ||
| //EncodeSSHKey
 | ||
| func EncodeSSHKey(public *rsa.PublicKey) ([]byte, error) {
 | ||
| 	publicKey, err := ssh.NewPublicKey(public)
 | ||
| 	if err != nil {
 | ||
| 		return nil, err
 | ||
| 	}
 | ||
| 	return ssh.MarshalAuthorizedKey(publicKey), nil
 | ||
| }
 | ||
| 
 | ||
| func MakeSSHKeyPair(bits int) (string, string, error) {
 | ||
| 
 | ||
| 	pkey, pubkey, err := GenerateKey(bits)
 | ||
| 	if err != nil {
 | ||
| 		return "", "", err
 | ||
| 	}
 | ||
| 
 | ||
| 	pub, err := EncodeSSHKey(pubkey)
 | ||
| 	if err != nil {
 | ||
| 		return "", "", err
 | ||
| 	}
 | ||
| 
 | ||
| 	//glog.Info("privateKey=[%s]\n pubKey=[%s]",string(EncodePrivateKey(pkey)),string(pub))
 | ||
| 	return string(EncodePrivateKey(pkey)), string(pub), nil
 | ||
| }
 | ||
| 
 | ||
| // RSAEncrypt RSA公钥加密
 | ||
| func RSAEncrypt(pub *rsa.PublicKey, data []byte) ([]byte, error) {
 | ||
| 	return rsa.EncryptPKCS1v15(rand.Reader, pub, data)
 | ||
| }
 | ||
| 
 | ||
| // RSADecrypt RSA私钥解密
 | ||
| func RSADecrypt(prikey *rsa.PrivateKey, data []byte) ([]byte, error) {
 | ||
| 	return rsa.DecryptPKCS1v15(rand.Reader, prikey, data)
 | ||
| }
 | ||
| 
 | ||
| // RSASign RSA私钥签名加密
 | ||
| func RSASign(msg, priKey []byte, password string, hashType crypto.Hash) ([]byte, error) {
 | ||
| 	var prikey *rsa.PrivateKey
 | ||
| 	var err error
 | ||
| 	var bytes []byte
 | ||
| 	blk, _ := pem.Decode(priKey)
 | ||
| 	if blk == nil {
 | ||
| 		return []byte{}, errors.New("private key error!")
 | ||
| 	}
 | ||
| 	if password != "" {
 | ||
| 		tmp, err := x509.DecryptPEMBlock(blk, []byte(password))
 | ||
| 		if err != nil {
 | ||
| 			return []byte{}, err
 | ||
| 		}
 | ||
| 		bytes = tmp
 | ||
| 	} else {
 | ||
| 		bytes = blk.Bytes
 | ||
| 	}
 | ||
| 	prikey, err = x509.ParsePKCS1PrivateKey(bytes)
 | ||
| 	if err != nil {
 | ||
| 		tmp, err := x509.ParsePKCS8PrivateKey(bytes)
 | ||
| 		if err != nil {
 | ||
| 			return []byte{}, err
 | ||
| 		}
 | ||
| 		prikey = tmp.(*rsa.PrivateKey)
 | ||
| 	}
 | ||
| 	hashMethod := hashType.New()
 | ||
| 	_, err = hashMethod.Write(msg)
 | ||
| 	if err != nil {
 | ||
| 		return nil, err
 | ||
| 	}
 | ||
| 	return rsa.SignPKCS1v15(rand.Reader, prikey, hashType, hashMethod.Sum(nil))
 | ||
| }
 | ||
| 
 | ||
| // RSAVerify RSA公钥签名验证
 | ||
| func RSAVerify(data, msg, pubKey []byte, hashType crypto.Hash) error {
 | ||
| 	blk, _ := pem.Decode(pubKey)
 | ||
| 	if blk == nil {
 | ||
| 		return errors.New("public key error!")
 | ||
| 	}
 | ||
| 	pubkey, err := x509.ParsePKIXPublicKey(blk.Bytes)
 | ||
| 	if err != nil {
 | ||
| 		return err
 | ||
| 	}
 | ||
| 	hashMethod := hashType.New()
 | ||
| 	_, err = hashMethod.Write(msg)
 | ||
| 	if err != nil {
 | ||
| 		return err
 | ||
| 	}
 | ||
| 	return rsa.VerifyPKCS1v15(pubkey.(*rsa.PublicKey), hashType, hashMethod.Sum(nil), data)
 | ||
| }
 | ||
| 
 | ||
| // copy from crypt/rsa/pkcs1v5.go
 | ||
| var hashPrefixes = map[crypto.Hash][]byte{
 | ||
| 	crypto.MD5:       {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
 | ||
| 	crypto.SHA1:      {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
 | ||
| 	crypto.SHA224:    {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
 | ||
| 	crypto.SHA256:    {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
 | ||
| 	crypto.SHA384:    {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
 | ||
| 	crypto.SHA512:    {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
 | ||
| 	crypto.MD5SHA1:   {}, // A special TLS case which doesn't use an ASN1 prefix.
 | ||
| 	crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
 | ||
| }
 | ||
| 
 | ||
| // copy from crypt/rsa/pkcs1v5.go
 | ||
| func encrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int {
 | ||
| 	e := big.NewInt(int64(pub.E))
 | ||
| 	c.Exp(m, e, pub.N)
 | ||
| 	return c
 | ||
| }
 | ||
| 
 | ||
| // copy from crypt/rsa/pkcs1v5.go
 | ||
| func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) {
 | ||
| 	// Special case: crypto.Hash(0) is used to indicate that the data is
 | ||
| 	// signed directly.
 | ||
| 	if hash == 0 {
 | ||
| 		return inLen, nil, nil
 | ||
| 	}
 | ||
| 
 | ||
| 	hashLen = hash.Size()
 | ||
| 	if inLen != hashLen {
 | ||
| 		return 0, nil, errors.New("crypto/rsa: input must be hashed message")
 | ||
| 	}
 | ||
| 	prefix, ok := hashPrefixes[hash]
 | ||
| 	if !ok {
 | ||
| 		return 0, nil, errors.New("crypto/rsa: unsupported hash function")
 | ||
| 	}
 | ||
| 	return
 | ||
| }
 | ||
| 
 | ||
| // copy from crypt/rsa/pkcs1v5.go
 | ||
| func leftPad(input []byte, size int) (out []byte) {
 | ||
| 	n := len(input)
 | ||
| 	if n > size {
 | ||
| 		n = size
 | ||
| 	}
 | ||
| 	out = make([]byte, size)
 | ||
| 	copy(out[len(out)-n:], input)
 | ||
| 	return
 | ||
| }
 | ||
| func unLeftPad(input []byte) (out []byte) {
 | ||
| 	n := len(input)
 | ||
| 	t := 2
 | ||
| 	for i := 2; i < n; i++ {
 | ||
| 		if input[i] == 0xff {
 | ||
| 			t = t + 1
 | ||
| 		} else {
 | ||
| 			if input[i] == input[0] {
 | ||
| 				t = t + int(input[1])
 | ||
| 			}
 | ||
| 			break
 | ||
| 		}
 | ||
| 	}
 | ||
| 	out = make([]byte, n-t)
 | ||
| 	copy(out, input[t:])
 | ||
| 	return
 | ||
| }
 | ||
| 
 | ||
| // copy&modified from crypt/rsa/pkcs1v5.go
 | ||
| func publicDecrypt(pub *rsa.PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (out []byte, err error) {
 | ||
| 	hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
 | ||
| 	if err != nil {
 | ||
| 		return nil, err
 | ||
| 	}
 | ||
| 
 | ||
| 	tLen := len(prefix) + hashLen
 | ||
| 	k := (pub.N.BitLen() + 7) / 8
 | ||
| 	if k < tLen+11 {
 | ||
| 		return nil, fmt.Errorf("length illegal")
 | ||
| 	}
 | ||
| 
 | ||
| 	c := new(big.Int).SetBytes(sig)
 | ||
| 	m := encrypt(new(big.Int), pub, c)
 | ||
| 	em := leftPad(m.Bytes(), k)
 | ||
| 	out = unLeftPad(em)
 | ||
| 
 | ||
| 	err = nil
 | ||
| 	return
 | ||
| }
 | ||
| 
 | ||
| func RSAEncryptByPrivkey(privt *rsa.PrivateKey, data []byte) ([]byte, error) {
 | ||
| 	signData, err := rsa.SignPKCS1v15(nil, privt, crypto.Hash(0), data)
 | ||
| 	if err != nil {
 | ||
| 		return nil, err
 | ||
| 	}
 | ||
| 	return signData, nil
 | ||
| }
 | ||
| 
 | ||
| func RSADecryptByPubkey(pub *rsa.PublicKey, data []byte) ([]byte, error) {
 | ||
| 	decData, err := publicDecrypt(pub, crypto.Hash(0), nil, data)
 | ||
| 	if err != nil {
 | ||
| 		return nil, err
 | ||
| 	}
 | ||
| 	return decData, nil
 | ||
| }
 |