rsa - skynocover/Wiki-for-GoLang GitHub Wiki

RSA

package rsa

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/subtle"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"math/big"
)

const bits = 2048

type RSA struct {
	PublicKey  []byte `json:"public"`
	PrivateKey []byte `json:"private"`
}

func (this *RSA) GenKey(bits int) error {

	priKey, err := rsa.GenerateKey(rand.Reader, bits)
	if err != nil {
		return err
	}

	pubKey := &priKey.PublicKey
	this.PrivateKey = x509.MarshalPKCS1PrivateKey(priKey)
	this.PublicKey, err = x509.MarshalPKIXPublicKey(pubKey)
	if err != nil {
		return err
	}
	return nil
}

func (this *RSA) Encode(data []byte) ([]byte, error) {
	priKey, err := x509.ParsePKCS1PrivateKey(this.PrivateKey)
	if err != nil {
		return nil, err
	}
	encryptMsg := []byte{}
	maxlength := bits/8 - 11

	i := 0
	for i < len(data) {
		j := i + maxlength
		if j > len(data) {
			j = len(data)
		}
		temp, err := rsa.SignPKCS1v15(rand.Reader, priKey, crypto.Hash(0), data[i:j])
		if err != nil {
			return nil, err
		}
		encryptMsg = append(encryptMsg, temp...)
		i += maxlength
	}
	return encryptMsg, nil
}

func (this *RSA) EncodePub(data []byte) ([]byte, error) {
	pubKey, err := x509.ParsePKIXPublicKey(this.PublicKey)
	if err != nil {
		return nil, err
	}
	pub := pubKey.(*rsa.PublicKey)

	encryption := []byte{}
	maxlength := bits/8 - 11

	i := 0
	for i < len(data) {
		j := i + maxlength
		if j > len(data) {
			j = len(data)
		}
		temp, err := rsa.EncryptPKCS1v15(rand.Reader, pub, data[i:j])
		if err != nil {
			return nil, err
		}
		encryption = append(encryption, temp...)
		i += maxlength
	}
	return encryption, nil
}

func (this *RSA) Pem() {
	if this.PrivateKey != nil {
		block := &pem.Block{
			Type:  "RSA PRIVATE KEY",
			Bytes: this.PrivateKey,
		}
		this.PrivateKey = pem.EncodeToMemory(block)
	}
	if this.PublicKey != nil {
		block := &pem.Block{
			Type:  "PUBLIC KEY",
			Bytes: this.PrivateKey,
		}
		this.PublicKey = pem.EncodeToMemory(block)
	}
}

func (this *RSA) DePemPub(deta []byte) ([]byte, error) {
	blockPub, _ := pem.Decode(this.PublicKey)
	if blockPub == nil {
		return nil, errors.New("blockPub空")
	}
	this.PublicKey = blockPub.Bytes
	return this.DecodePub(deta)
}

func (this *RSA) DePemPri(deta []byte) ([]byte, error) {
	blockPri, _ := pem.Decode(this.PrivateKey)
	if blockPri == nil {
		return nil, errors.New("blockPub空")
	}
	this.PrivateKey = blockPri.Bytes
	return this.Decode(deta)
}

func (this *RSA) DecodePub(deta []byte) ([]byte, error) {
	pubKey, err := x509.ParsePKIXPublicKey(this.PublicKey)
	if err != nil {
		return nil, err
	}

	decryptMsg := decrypt(pubKey.(*rsa.PublicKey), deta)
	return decryptMsg, nil
}

func (this *RSA) Decode(deta []byte) ([]byte, error) {
	prkI, err := x509.ParsePKCS1PrivateKey(this.PrivateKey)
	if err != nil {
		return nil, err
	}

	decode := []byte{}
	i := 0
	for i < len(deta) {
		j := i + bits/8
		if j > len(deta) {
			j = len(deta)
		}
		temp, err := rsa.DecryptPKCS1v15(rand.Reader, prkI, deta[i:j])

		if err != nil {
			return nil, err
		}
		decode = append(decode, temp...)
		i += bits / 8
	}
	return decode, nil
}

func decrypt(pub *rsa.PublicKey, sig []byte) []byte {
	k := (pub.N.BitLen() + 7) / 8
	m := new(big.Int)
	c := new(big.Int).SetBytes(sig)
	e := big.NewInt(int64(pub.E))
	m.Exp(c, e, pub.N)
	em := leftPad(m.Bytes(), k)
	firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
	secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 1)
	lookingForIndex := 1
	index := 0
	for i := 2; i < len(em); i++ {
		equals0 := subtle.ConstantTimeByteEq(em[i], 0)
		index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
		lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
	}
	validPS := subtle.ConstantTimeLessOrEq(2+8, index)
	valid := firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS
	index = subtle.ConstantTimeSelect(valid, index+1, 0)
	return em[index:]
}

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
}