init: v1.0.0
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
//go:build !gmp
|
||||
// +build !gmp
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/internal/randutil"
|
||||
)
|
||||
|
||||
type Int = big.Int
|
||||
|
||||
var bigOne = new(big.Int).SetInt64(1)
|
||||
|
||||
func FromBigInt(src *big.Int) *Int {
|
||||
return src
|
||||
}
|
||||
func IntoBigInt(src *Int) *big.Int {
|
||||
return src
|
||||
}
|
||||
|
||||
func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
|
||||
e := big.NewInt(int64(pub.E))
|
||||
c.Exp(m, e, pub.N)
|
||||
return c
|
||||
}
|
||||
|
||||
// decrypt performs an RSA decryption, resulting in a plaintext integer. If a
|
||||
// random source is given, RSA blinding is used.
|
||||
func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
|
||||
// TODO(agl): can we get away with reusing blinds?
|
||||
if c.Cmp(priv.N) > 0 {
|
||||
err = ErrDecryption
|
||||
return
|
||||
}
|
||||
if priv.N.Sign() == 0 {
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
|
||||
var ir *big.Int
|
||||
if random != nil {
|
||||
randutil.MaybeReadByte(random)
|
||||
|
||||
// Blinding enabled. Blinding involves multiplying c by r^e.
|
||||
// Then the decryption operation performs (m^e * r^e)^d mod n
|
||||
// which equals mr mod n. The factor of r can then be removed
|
||||
// by multiplying by the multiplicative inverse of r.
|
||||
|
||||
var r *big.Int
|
||||
ir = new(big.Int)
|
||||
for {
|
||||
r, err = rand.Int(random, priv.N)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// if r.Cmp(bigZero) == 0 {
|
||||
if r.Sign() == 0 {
|
||||
r = bigOne
|
||||
}
|
||||
ok := ir.ModInverse(r, priv.N)
|
||||
if ok != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
bigE := big.NewInt(int64(priv.E))
|
||||
rpowe := new(big.Int).Exp(r, bigE, priv.N) // N != 0
|
||||
cCopy := new(big.Int).Set(c)
|
||||
cCopy.Mul(cCopy, rpowe)
|
||||
cCopy.Mod(cCopy, priv.N)
|
||||
c = cCopy
|
||||
}
|
||||
|
||||
if priv.Precomputed.Dp == nil {
|
||||
m = new(big.Int).Exp(c, priv.D, priv.N)
|
||||
} else {
|
||||
// We have the precalculated values needed for the CRT.
|
||||
m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0])
|
||||
m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1])
|
||||
m.Sub(m, m2)
|
||||
if m.Sign() < 0 {
|
||||
m.Add(m, priv.Primes[0])
|
||||
}
|
||||
m.Mul(m, priv.Precomputed.Qinv)
|
||||
m.Mod(m, priv.Primes[0])
|
||||
m.Mul(m, priv.Primes[1])
|
||||
m.Add(m, m2)
|
||||
|
||||
for i, values := range priv.Precomputed.CRTValues {
|
||||
prime := priv.Primes[2+i]
|
||||
m2.Exp(c, values.Exp, prime)
|
||||
m2.Sub(m2, m)
|
||||
m2.Mul(m2, values.Coeff)
|
||||
m2.Mod(m2, prime)
|
||||
if m2.Sign() < 0 {
|
||||
m2.Add(m2, prime)
|
||||
}
|
||||
m2.Mul(m2, values.R)
|
||||
m.Add(m, m2)
|
||||
}
|
||||
}
|
||||
|
||||
if ir != nil {
|
||||
// Unblind.
|
||||
m.Mul(m, ir)
|
||||
m.Mod(m, priv.N)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
//go:build gmp
|
||||
// +build gmp
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/api/common"
|
||||
"xdx.jelly/xgcl/internal/gmp"
|
||||
"xdx.jelly/xgcl/internal/randutil"
|
||||
)
|
||||
|
||||
type Int = gmp.Int
|
||||
|
||||
var bigOne = big.NewInt(1)
|
||||
|
||||
func FromBigInt(src *big.Int) *Int {
|
||||
dst := new(Int)
|
||||
dst.SetBytes(src.Bytes())
|
||||
return dst
|
||||
}
|
||||
|
||||
func IntoBigInt(src *Int) *big.Int {
|
||||
dst := new(big.Int)
|
||||
dst.SetBytes(src.Bytes())
|
||||
return dst
|
||||
}
|
||||
|
||||
func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
|
||||
e := new(Int).SetInt64(int64(pub.E))
|
||||
cc := FromBigInt(c)
|
||||
cc.Exp(FromBigInt(m), e, FromBigInt(pub.N))
|
||||
c.SetBytes(cc.Bytes())
|
||||
return c
|
||||
}
|
||||
|
||||
// decrypt performs an RSA decryption, resulting in a plaintext integer. If a
|
||||
// random source is given, RSA blinding is used.
|
||||
func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
|
||||
// TODO(agl): can we get away with reusing blinds?
|
||||
if c.Cmp(priv.N) > 0 {
|
||||
err = common.SDR_KEYERR
|
||||
return
|
||||
}
|
||||
if priv.N.Sign() == 0 {
|
||||
return nil, common.SDR_KEYERR
|
||||
}
|
||||
|
||||
var ir *Int
|
||||
modulus := FromBigInt(priv.N)
|
||||
d := FromBigInt(priv.D)
|
||||
// if random != nil {
|
||||
if false {
|
||||
randutil.MaybeReadByte(random)
|
||||
|
||||
// Blinding enabled. Blinding involves multiplying c by r^e.
|
||||
// Then the decryption operation performs (m^e * r^e)^d mod n
|
||||
// which equals mr mod n. The factor of r can then be removed
|
||||
// by multiplying by the multiplicative inverse of r.
|
||||
var r *Int
|
||||
ir = new(Int)
|
||||
|
||||
for {
|
||||
var R *big.Int
|
||||
R, err = rand.Int(random, priv.N)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if R.Sign() == 0 {
|
||||
R = bigOne
|
||||
}
|
||||
r = FromBigInt(R)
|
||||
ok := ir.ModInverse(r, modulus)
|
||||
if ok != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
bigE := new(Int).SetInt64(int64(priv.E))
|
||||
rpowe := new(Int).Exp(r, bigE, modulus) // N != 0
|
||||
cCopy := new(Int).Set(FromBigInt(c))
|
||||
cCopy.Mul(cCopy, rpowe)
|
||||
cCopy.Mod(cCopy, modulus)
|
||||
c = IntoBigInt(cCopy)
|
||||
}
|
||||
|
||||
var mm *Int
|
||||
if priv.Precomputed.Dp == nil {
|
||||
m = IntoBigInt(new(Int).Exp(FromBigInt(c), d, modulus))
|
||||
} else {
|
||||
// We have the precalculated values needed for the CRT.
|
||||
cc := FromBigInt(c)
|
||||
primes0 := FromBigInt(priv.Primes[0])
|
||||
primes1 := FromBigInt(priv.Primes[1])
|
||||
mm = new(Int).Exp(cc, FromBigInt(priv.Precomputed.Dp), primes0)
|
||||
mm2 := new(Int).Exp(cc, FromBigInt(priv.Precomputed.Dq), primes1)
|
||||
mm.Sub(mm, mm2)
|
||||
if mm.Sign() < 0 {
|
||||
mm.Add(mm, primes0)
|
||||
}
|
||||
mm.Mul(mm, FromBigInt(priv.Precomputed.Qinv))
|
||||
mm.Mod(mm, primes0)
|
||||
mm.Mul(mm, primes1)
|
||||
mm.Add(mm, mm2)
|
||||
|
||||
for i, values := range priv.Precomputed.CRTValues {
|
||||
prime := FromBigInt(priv.Primes[2+i])
|
||||
mm2.Exp(cc, FromBigInt(values.Exp), prime)
|
||||
mm2.Sub(mm2, mm)
|
||||
mm2.Mul(mm2, FromBigInt(values.Coeff))
|
||||
mm2.Mod(mm2, prime)
|
||||
if mm2.Sign() < 0 {
|
||||
mm2.Add(mm2, prime)
|
||||
}
|
||||
mm2.Mul(mm2, FromBigInt(values.R))
|
||||
mm.Add(mm, mm2)
|
||||
}
|
||||
}
|
||||
|
||||
if ir != nil {
|
||||
// Unblind.
|
||||
mm.Mul(mm, ir)
|
||||
mm.Mod(mm, modulus)
|
||||
}
|
||||
m = IntoBigInt(mm)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,693 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package rsa implements RSA encryption as specified in PKCS #1 and RFC 8017.
|
||||
//
|
||||
// RSA is a single, fundamental operation that is used in this package to
|
||||
// implement either public-key encryption or public-key signatures.
|
||||
//
|
||||
// The original specification for encryption and signatures with RSA is PKCS #1
|
||||
// and the terms "RSA encryption" and "RSA signatures" by default refer to
|
||||
// PKCS #1 version 1.5. However, that specification has flaws and new designs
|
||||
// should use version 2, usually called by just OAEP and PSS, where
|
||||
// possible.
|
||||
//
|
||||
// Two sets of interfaces are included in this package. When a more abstract
|
||||
// interface isn't necessary, there are functions for encrypting/decrypting
|
||||
// with v1.5/OAEP and signing/verifying with v1.5/PSS. If one needs to abstract
|
||||
// over the public key primitive, the PrivateKey type implements the
|
||||
// Decrypter and Signer interfaces from the crypto package.
|
||||
//
|
||||
// The RSA operations in this package are not implemented using constant-time algorithms.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
cryptoRSA "crypto/rsa"
|
||||
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/api/common"
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/internal/randutil"
|
||||
"xdx.jelly/xgcl/sm"
|
||||
)
|
||||
|
||||
// A PublicKey represents the public part of an RSA key.
|
||||
type PublicKey struct {
|
||||
N *big.Int // modulus
|
||||
E int // public exponent
|
||||
}
|
||||
|
||||
func NewPublicKey() *PublicKey {
|
||||
return &PublicKey{
|
||||
N: new(big.Int),
|
||||
}
|
||||
}
|
||||
|
||||
type PrecomputedValues = cryptoRSA.PrecomputedValues
|
||||
|
||||
// type PrecomputedValues struct {
|
||||
// Dp, Dq *big.Int // D mod (P-1) (or mod Q-1)
|
||||
// Qinv *big.Int // Q^-1 mod P
|
||||
|
||||
// // CRTValues is used for the 3rd and subsequent primes. Due to a
|
||||
// // historical accident, the CRT for the first two primes is handled
|
||||
// // differently in PKCS #1 and interoperability is sufficiently
|
||||
// // important that we mirror this.
|
||||
// CRTValues []CRTValue
|
||||
// }
|
||||
|
||||
// CRTValue contains the precomputed Chinese remainder theorem values.
|
||||
type CRTValue = cryptoRSA.CRTValue
|
||||
|
||||
// type CRTValue struct {
|
||||
// Exp *big.Int // D mod (prime-1).
|
||||
// Coeff *big.Int // R·Coeff ≡ 1 mod Prime.
|
||||
// R *big.Int // product of primes prior to this (inc p and q).
|
||||
// }
|
||||
|
||||
// A PrivateKey represents an RSA key
|
||||
// type PrivateKey = rsa.PrivateKey
|
||||
type PrivateKey struct {
|
||||
PublicKey // public part.
|
||||
D *big.Int // private exponent
|
||||
Primes []*big.Int // prime factors of N, has >= 2 elements.
|
||||
|
||||
// Precomputed contains precomputed values that speed up private
|
||||
// operations, if available.
|
||||
Precomputed PrecomputedValues
|
||||
}
|
||||
|
||||
func NewPrivateKey() *PrivateKey {
|
||||
return &PrivateKey{
|
||||
PublicKey: PublicKey{
|
||||
N: new(big.Int),
|
||||
},
|
||||
D: new(big.Int),
|
||||
Primes: []*big.Int{new(big.Int), new(big.Int)},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (pub *PublicKey) From(k *cryptoRSA.PublicKey) {
|
||||
pub.N = k.N
|
||||
pub.E = k.E
|
||||
}
|
||||
|
||||
func (pub *PublicKey) UnmarshalCryptoRsa(k *cryptoRSA.PublicKey) *PublicKey {
|
||||
pub.From(k)
|
||||
return pub
|
||||
}
|
||||
|
||||
func (pub *PublicKey) Into() *cryptoRSA.PublicKey {
|
||||
return &cryptoRSA.PublicKey{
|
||||
N: pub.N,
|
||||
E: pub.E,
|
||||
}
|
||||
}
|
||||
|
||||
func (pub *PublicKey) Equal(x crypto.PublicKey) bool {
|
||||
switch xx := x.(type) {
|
||||
case *PublicKey:
|
||||
return pub.N.Cmp(xx.N) == 0 && pub.E == xx.E
|
||||
case *cryptoRSA.PublicKey:
|
||||
return pub.N.Cmp(xx.N) == 0 && pub.E == xx.E
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (priv *PrivateKey) From(k *cryptoRSA.PrivateKey) *PrivateKey {
|
||||
priv.PublicKey.From(&k.PublicKey)
|
||||
priv.D = k.D
|
||||
priv.Primes = k.Primes
|
||||
priv.Precomputed = k.Precomputed
|
||||
return priv
|
||||
}
|
||||
|
||||
func (priv *PrivateKey) Into() *cryptoRSA.PrivateKey {
|
||||
return &cryptoRSA.PrivateKey{
|
||||
PublicKey: cryptoRSA.PublicKey{
|
||||
N: priv.PublicKey.N,
|
||||
E: priv.PublicKey.E,
|
||||
},
|
||||
D: priv.D,
|
||||
Primes: priv.Primes,
|
||||
Precomputed: priv.Precomputed,
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
errPublicModulus = errors.New("crypto/rsa: missing public modulus")
|
||||
errPublicExponentSmall = errors.New("crypto/rsa: public exponent too small")
|
||||
errPublicExponentLarge = errors.New("crypto/rsa: public exponent too large")
|
||||
)
|
||||
|
||||
// checkPub sanity checks the public key before we use it.
|
||||
// We require pub.E to fit into a 32-bit integer so that we
|
||||
// do not have different behavior depending on whether
|
||||
// int is 32 or 64 bits. See also
|
||||
// https://www.imperialviolet.org/2012/03/16/rsae.html.
|
||||
func checkPub(pub *PublicKey) error {
|
||||
if pub.N == nil {
|
||||
return errPublicModulus
|
||||
}
|
||||
if pub.E < 2 {
|
||||
return errPublicExponentSmall
|
||||
}
|
||||
if pub.E > 1<<31-1 {
|
||||
return errPublicExponentLarge
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate performs basic sanity checks on the key.
|
||||
// It returns nil if the key is valid, or else an error describing a problem.
|
||||
func (priv *PrivateKey) Validate() error {
|
||||
if err := checkPub(&priv.PublicKey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check that Πprimes == n.
|
||||
modulus := new(big.Int).Set(bigOne)
|
||||
for _, prime := range priv.Primes {
|
||||
// Any primes ≤ 1 will cause divide-by-zero panics later.
|
||||
if prime.Cmp(bigOne) <= 0 {
|
||||
return errors.New("crypto/rsa: invalid prime value")
|
||||
}
|
||||
modulus.Mul(modulus, prime)
|
||||
}
|
||||
if modulus.Cmp(priv.N) != 0 {
|
||||
return errors.New("crypto/rsa: invalid modulus")
|
||||
}
|
||||
|
||||
// Check that de ≡ 1 mod p-1, for each prime.
|
||||
// This implies that e is coprime to each p-1 as e has a multiplicative
|
||||
// inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) =
|
||||
// exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1
|
||||
// mod p. Thus a^de ≡ a mod n for all a coprime to n, as required.
|
||||
congruence := new(big.Int)
|
||||
de := new(big.Int).SetInt64(int64(priv.E))
|
||||
de.Mul(de, priv.D)
|
||||
for _, prime := range priv.Primes {
|
||||
pminus1 := new(big.Int).Sub(prime, bigOne)
|
||||
congruence.Mod(de, pminus1)
|
||||
if congruence.Cmp(bigOne) != 0 {
|
||||
return errors.New("crypto/rsa: invalid exponents")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Precompute performs some calculations that speed up private key operations
|
||||
// in the future.
|
||||
func (priv *PrivateKey) Precompute() {
|
||||
if priv.Precomputed.Dp != nil {
|
||||
return
|
||||
}
|
||||
|
||||
priv.Precomputed.Dp = new(big.Int).Sub(priv.Primes[0], bigOne)
|
||||
priv.Precomputed.Dp.Mod(priv.D, priv.Precomputed.Dp)
|
||||
|
||||
priv.Precomputed.Dq = new(big.Int).Sub(priv.Primes[1], bigOne)
|
||||
priv.Precomputed.Dq.Mod(priv.D, priv.Precomputed.Dq)
|
||||
|
||||
priv.Precomputed.Qinv = new(big.Int).ModInverse(priv.Primes[1], priv.Primes[0])
|
||||
|
||||
r := new(big.Int).Mul(priv.Primes[0], priv.Primes[1])
|
||||
priv.Precomputed.CRTValues = make([]CRTValue, len(priv.Primes)-2)
|
||||
for i := 2; i < len(priv.Primes); i++ {
|
||||
prime := priv.Primes[i]
|
||||
values := &priv.Precomputed.CRTValues[i-2]
|
||||
|
||||
values.Exp = new(big.Int).Sub(prime, bigOne)
|
||||
values.Exp.Mod(priv.D, values.Exp)
|
||||
|
||||
values.R = new(big.Int).Set(r)
|
||||
values.Coeff = new(big.Int).ModInverse(r, prime)
|
||||
|
||||
r.Mul(r, prime)
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalSDF import privateKey from SDF type.
|
||||
func (priv *PrivateKey) UnmarshalSDF(sdfPriv *common.RSArefPrivateKey) error {
|
||||
return priv.FromSDF(sdfPriv)
|
||||
}
|
||||
func (priv *PrivateKey) FromSDF(sdfPriv *common.RSArefPrivateKey) error {
|
||||
if priv.PublicKey.N == nil {
|
||||
priv.PublicKey.N = new(big.Int)
|
||||
}
|
||||
priv.N.SetBytes(sdfPriv.M[:])
|
||||
|
||||
if priv.D == nil {
|
||||
priv.D = new(big.Int)
|
||||
}
|
||||
priv.D.SetBytes(sdfPriv.D[:])
|
||||
|
||||
// E always be 65537
|
||||
e := new(big.Int).SetBytes(sdfPriv.E[:])
|
||||
if e.BitLen() > 32 {
|
||||
return common.SDR_KEYERR
|
||||
}
|
||||
priv.E = int(e.Uint64())
|
||||
|
||||
priv.Primes = append(priv.Primes[:0], new(big.Int).SetBytes(sdfPriv.Prime[0][:]))
|
||||
priv.Primes = append(priv.Primes, new(big.Int).SetBytes(sdfPriv.Prime[1][:]))
|
||||
priv.Precompute()
|
||||
return priv.Validate()
|
||||
}
|
||||
|
||||
// Export export privateKey to SDF type.
|
||||
func (priv *PrivateKey) IntoSDF() (*common.RSArefPrivateKey, error) {
|
||||
ret := &common.RSArefPrivateKey{}
|
||||
if err := priv.UnmarshalSDF(ret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (priv *PrivateKey) MarshalSDF(sdfPriv *common.RSArefPrivateKey) error {
|
||||
if err := priv.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
priv.Precompute()
|
||||
sdfPriv.Bits = uint32(priv.N.BitLen())
|
||||
if sdfPriv.Bits > common.RSAref_MAX_BITS || len(priv.Primes) != 2 {
|
||||
return common.SDR_KEYERR
|
||||
}
|
||||
_ = gmath.FillBytes(priv.N, sdfPriv.M[:])
|
||||
_ = gmath.FillBytes(new(big.Int).SetInt64(int64(priv.E)), sdfPriv.E[:]) // FIXME
|
||||
_ = gmath.FillBytes(priv.D, sdfPriv.D[:])
|
||||
_ = gmath.FillBytes(priv.Primes[0], sdfPriv.Prime[0][:])
|
||||
_ = gmath.FillBytes(priv.Primes[1], sdfPriv.Prime[1][:])
|
||||
_ = gmath.FillBytes(priv.Precomputed.Dp, sdfPriv.Pexp[0][:])
|
||||
_ = gmath.FillBytes(priv.Precomputed.Dq, sdfPriv.Pexp[1][:])
|
||||
_ = gmath.FillBytes(priv.Precomputed.Qinv, sdfPriv.Coef[:])
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set set pbulicKey directly by M and E, big-endian bytes.
|
||||
func (pub *PublicKey) Set(M []byte, E []byte) error {
|
||||
if pub.N == nil {
|
||||
pub.N = new(big.Int)
|
||||
}
|
||||
pub.N.SetBytes(M[:])
|
||||
|
||||
e := new(Int).SetBytes(E[:])
|
||||
if e.BitLen() > 32 {
|
||||
return common.SDR_KEYERR
|
||||
}
|
||||
pub.E = int(e.Uint64())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pub *PublicKey) IntoSDF() (*common.RSArefPublicKey, error) {
|
||||
ret := &common.RSArefPublicKey{}
|
||||
if err := pub.MarshalSDF(ret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// MarshalSDF export publicKey to SDF type.
|
||||
func (pub *PublicKey) MarshalSDF(sdfPub *common.RSArefPublicKey) error {
|
||||
if err := checkPub(pub); err != nil {
|
||||
return err
|
||||
}
|
||||
sdfPub.Bits = uint32(pub.N.BitLen())
|
||||
if sdfPub.Bits > common.RSAref_MAX_BITS {
|
||||
return common.SDR_KEYERR
|
||||
}
|
||||
_ = gmath.FillBytes(pub.N, sdfPub.M[:])
|
||||
_ = gmath.FillBytes(new(big.Int).SetInt64(int64(pub.E)), sdfPub.E[:]) // FIXME
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalSDF import publicKey from SDF type.
|
||||
func (pub *PublicKey) UnmarshalSDF(sdfPub *common.RSArefPublicKey) error {
|
||||
return pub.FromSDF(sdfPub)
|
||||
}
|
||||
func (pub *PublicKey) FromSDF(sdfPub *common.RSArefPublicKey) error {
|
||||
if pub.N == nil {
|
||||
pub.N = new(big.Int)
|
||||
}
|
||||
pub.N.SetBytes(sdfPub.M[:])
|
||||
|
||||
e := new(big.Int).SetBytes(sdfPub.E[:])
|
||||
if e.BitLen() > 32 {
|
||||
return common.SDR_KEYERR
|
||||
}
|
||||
pub.E = int(e.Uint64())
|
||||
return checkPub(pub)
|
||||
}
|
||||
|
||||
// Size returns the modulus size in bytes. Raw signatures and ciphertexts
|
||||
// for or by this public key will have the same size.
|
||||
func (pub *PublicKey) Size() int {
|
||||
return (pub.N.BitLen() + 7) / 8
|
||||
}
|
||||
|
||||
// GenerateKey generates an RSA keypair of the given bit size using the
|
||||
// random source random (for example, crypto/rand.Reader).
|
||||
func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) {
|
||||
priv, err := cryptoRSA.GenerateKey(random, bits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
privateKey := &PrivateKey{}
|
||||
privateKey.From(priv)
|
||||
return privateKey, nil
|
||||
}
|
||||
|
||||
// ErrDecryption represents a failure to decrypt a message.
|
||||
// It is deliberately vague to avoid adaptive attacks.
|
||||
var ErrDecryption = errors.New("crypto/rsa: decryption error")
|
||||
|
||||
// ErrVerification represents a failure to verify a signature.
|
||||
// It is deliberately vague to avoid adaptive attacks.
|
||||
var ErrVerification = errors.New("crypto/rsa: verification error")
|
||||
|
||||
// ErrMessageTooLong is returned when attempting to encrypt a message which is
|
||||
// too large for the size of the public key.
|
||||
var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA public key size")
|
||||
|
||||
// This file implements encryption and decryption using PKCS #1 v1.5 padding.
|
||||
|
||||
// PKCS1v15DecrypterOpts is for passing options to PKCS #1 v1.5 decryption using
|
||||
// the crypto.Decrypter interface.
|
||||
type PKCS1v15DecryptOptions = cryptoRSA.PKCS1v15DecryptOptions
|
||||
|
||||
// EncryptPKCS1v15 encrypts the given message with RSA and the padding
|
||||
// scheme from PKCS #1 v1.5. The message must be no longer than the
|
||||
// length of the public modulus minus 11 bytes.
|
||||
//
|
||||
// The rand parameter is used as a source of entropy to ensure that
|
||||
// encrypting the same message twice doesn't result in the same
|
||||
// ciphertext.
|
||||
//
|
||||
// WARNING: use of this function to encrypt plaintexts other than
|
||||
// session keys is dangerous. Use RSA OAEP in new protocols.
|
||||
func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error) {
|
||||
// return rsa.EncryptPKCS1v15(rand, pub.Into(), msg)
|
||||
randutil.MaybeReadByte(rand)
|
||||
|
||||
if err := checkPub(pub); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
k := pub.Size()
|
||||
if len(msg) > k-11 {
|
||||
return nil, ErrMessageTooLong
|
||||
}
|
||||
|
||||
// EM = 0x00 || 0x02 || PS || 0x00 || M
|
||||
em := make([]byte, k)
|
||||
em[1] = 2
|
||||
ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):]
|
||||
err := nonZeroRandomBytes(ps, rand)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
em[len(em)-len(msg)-1] = 0
|
||||
copy(mm, msg)
|
||||
|
||||
m := new(big.Int).SetBytes(em)
|
||||
c := encrypt(new(big.Int), pub, m)
|
||||
gmath.FillBytes(c, em)
|
||||
return em, nil
|
||||
}
|
||||
|
||||
// DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS #1 v1.5.
|
||||
// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
|
||||
//
|
||||
// Note that whether this function returns an error or not discloses secret
|
||||
// information. If an attacker can cause this function to run repeatedly and
|
||||
// learn whether each instance returned an error then they can decrypt and
|
||||
// forge signatures as if they had the private key. See
|
||||
// DecryptPKCS1v15SessionKey for a way of solving this problem.
|
||||
func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error) {
|
||||
// return rsa.DecryptPKCS1v15(rand, priv.Into(), ciphertext)
|
||||
if err := checkPub(&priv.PublicKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if valid == 0 {
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
return out[index:], nil
|
||||
}
|
||||
|
||||
// decryptPKCS1v15 decrypts ciphertext using priv and blinds the operation if
|
||||
// rand is not nil. It returns one or zero in valid that indicates whether the
|
||||
// plaintext was correctly structured. In either case, the plaintext is
|
||||
// returned in em so that it may be read independently of whether it was valid
|
||||
// in order to maintain constant memory access patterns. If the plaintext was
|
||||
// valid then index contains the index of the original message in em.
|
||||
func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) {
|
||||
k := priv.Size()
|
||||
if k < 11 {
|
||||
err = ErrDecryption
|
||||
return
|
||||
}
|
||||
|
||||
c := new(big.Int).SetBytes(ciphertext)
|
||||
m, err := decrypt(rand, priv, c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
em = m.FillBytes(make([]byte, k))
|
||||
firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
|
||||
secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
|
||||
|
||||
// The remainder of the plaintext must be a string of non-zero random
|
||||
// octets, followed by a 0, followed by the message.
|
||||
// lookingForIndex: 1 iff we are still looking for the zero.
|
||||
// index: the offset of the first zero byte.
|
||||
lookingForIndex := 1
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// The PS padding must be at least 8 bytes long, and it starts two
|
||||
// bytes into em.
|
||||
validPS := subtle.ConstantTimeLessOrEq(2+8, index)
|
||||
|
||||
valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS
|
||||
index = subtle.ConstantTimeSelect(valid, index+1, 0)
|
||||
return valid, em, index, nil
|
||||
}
|
||||
|
||||
// nonZeroRandomBytes fills the given slice with non-zero random octets.
|
||||
func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
|
||||
_, err = io.ReadFull(rand, s)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < len(s); i++ {
|
||||
for s[i] == 0 {
|
||||
_, err = io.ReadFull(rand, s[i:i+1])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// In tests, the PRNG may return all zeros so we do
|
||||
// this to break the loop.
|
||||
s[i] ^= 0x42
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// These are ASN1 DER structures:
|
||||
// DigestInfo ::= SEQUENCE {
|
||||
// digestAlgorithm AlgorithmIdentifier,
|
||||
// digest OCTET STRING
|
||||
// }
|
||||
// For performance, we don't use the generic ASN1 encoder. Rather, we
|
||||
// precompute a prefix of the digest value that makes a valid ASN1 DER string
|
||||
// with the correct contents.
|
||||
var hashPrefixes = map[sm.Hash][]byte{
|
||||
{Hash: crypto.SHA1}: {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
|
||||
{Hash: crypto.SHA256}: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
|
||||
sm.SM3: {0x30, 0x2e, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x81, 0x1c, 0xcf, 0x55, 0x01, 0x83, 0x11, 0x01, 0x05, 0x00, 0x04, 0x20},
|
||||
}
|
||||
|
||||
func pkcs1v15HashInfo(hash sm.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.Hash == 0 {
|
||||
return inLen, nil, nil
|
||||
}
|
||||
|
||||
hashLen = hash.Size()
|
||||
if inLen != hashLen {
|
||||
return 0, nil, errors.New("gcl/rsa: input must be hashed message")
|
||||
}
|
||||
prefix, ok := hashPrefixes[hash]
|
||||
if !ok {
|
||||
return 0, nil, errors.New("gcl/rsa: unsupported hash function")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SignPKCS1v15 calculates the signature of hashed using
|
||||
// RSASSA-PKCS1-V1_5-SIGN from RSA PKCS #1 v1.5. Note that hashed must
|
||||
// be the result of hashing the input message using the given hash
|
||||
// function. If hash is zero, hashed is signed directly. This isn't
|
||||
// advisable except for interoperability.
|
||||
//
|
||||
// If rand is not nil then RSA blinding will be used to avoid timing
|
||||
// side-channel attacks.
|
||||
//
|
||||
// This function is deterministic. Thus, if the set of possible
|
||||
// messages is small, an attacker may be able to build a map from
|
||||
// messages to signatures and identify the signed messages. As ever,
|
||||
// signatures provide authenticity, not confidentiality.
|
||||
func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash sm.Hash, hashed []byte) ([]byte, error) {
|
||||
hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tLen := len(prefix) + hashLen
|
||||
k := priv.Size()
|
||||
if k < tLen+11 {
|
||||
return nil, errors.New("rsa: message too long for RSA public key size")
|
||||
}
|
||||
|
||||
// EM = 0x00 || 0x01 || PS || 0x00 || T
|
||||
em := make([]byte, k)
|
||||
em[1] = 1
|
||||
for i := 2; i < k-tLen-1; i++ {
|
||||
em[i] = 0xff
|
||||
}
|
||||
copy(em[k-tLen:k-hashLen], prefix)
|
||||
copy(em[k-hashLen:k], hashed)
|
||||
|
||||
m := new(big.Int).SetBytes(em)
|
||||
c, err := decryptAndCheck(rand, priv, m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.FillBytes(em), nil
|
||||
|
||||
// return rsa.SignPKCS1v15(rand, priv, hash.Hash, hashed)
|
||||
}
|
||||
|
||||
// VerifyPKCS1v15 verifies an RSA PKCS #1 v1.5 signature.
|
||||
// hashed is the result of hashing the input message using the given hash
|
||||
// function and sig is the signature. A valid signature is indicated by
|
||||
// returning a nil error. If hash is zero then hashed is used directly. This
|
||||
// isn't advisable except for interoperability.
|
||||
func VerifyPKCS1v15(pub *PublicKey, hash sm.Hash, hashed []byte, sig []byte) error {
|
||||
hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tLen := len(prefix) + hashLen
|
||||
k := pub.Size()
|
||||
if k < tLen+11 {
|
||||
return ErrVerification
|
||||
}
|
||||
|
||||
// RFC 8017 Section 8.2.2: If the length of the signature S is not k
|
||||
// octets (where k is the length in octets of the RSA modulus n), output
|
||||
// "invalid signature" and stop.
|
||||
if k != len(sig) {
|
||||
return ErrVerification
|
||||
}
|
||||
|
||||
c := new(big.Int).SetBytes(sig)
|
||||
m := encrypt(new(big.Int), pub, c)
|
||||
em := m.FillBytes(make([]byte, k))
|
||||
// EM = 0x00 || 0x01 || PS || 0x00 || T
|
||||
|
||||
ok := subtle.ConstantTimeByteEq(em[0], 0)
|
||||
ok &= subtle.ConstantTimeByteEq(em[1], 1)
|
||||
ok &= subtle.ConstantTimeCompare(em[k-hashLen:k], hashed)
|
||||
ok &= subtle.ConstantTimeCompare(em[k-tLen:k-hashLen], prefix)
|
||||
ok &= subtle.ConstantTimeByteEq(em[k-tLen-1], 0)
|
||||
|
||||
for i := 2; i < k-tLen-1; i++ {
|
||||
ok &= subtle.ConstantTimeByteEq(em[i], 0xff)
|
||||
}
|
||||
|
||||
if ok != 1 {
|
||||
return ErrVerification
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
// return rsa.VerifyPKCS1v15(pub, hash.Hash, hashed, sig)
|
||||
}
|
||||
|
||||
func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
|
||||
m, err = decrypt(random, priv, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// In order to defend against errors in the CRT computation, m^e is
|
||||
// calculated, which should match the original ciphertext.
|
||||
check := encrypt(new(big.Int), &priv.PublicKey, m)
|
||||
if c.Cmp(check) != 0 {
|
||||
return nil, errors.New("rsa: internal error")
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// PublicKeyOperationRSA RSA公钥运算。数据格式由应用层封装。inData 应该小于 privateKey.Size()
|
||||
func PublicKeyOperationRSA(publicKey *PublicKey, inData []byte) ([]byte, error) {
|
||||
m := new(big.Int).SetBytes(inData)
|
||||
if m.Cmp(publicKey.N) >= 0 {
|
||||
return nil, common.SDR_INARGERR
|
||||
}
|
||||
c := encrypt(new(big.Int), publicKey, m)
|
||||
ret := make([]byte, common.RSAref_MAX_LEN)
|
||||
err := gmath.FillBytes(c, ret)
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// PrivateKeyOperationRSA RSA私钥运算。数据格式由应用层封装。inData 应该小于 privateKey.Bits/8
|
||||
func PrivateKeyOperationRSA(privateKey *PrivateKey, inData []byte) ([]byte, error) {
|
||||
c := new(big.Int).SetBytes(inData)
|
||||
if c.Cmp(privateKey.N) >= 0 {
|
||||
return nil, common.SDR_INARGERR
|
||||
}
|
||||
m, err := decrypt(nil, privateKey, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := make([]byte, common.RSAref_MAX_LEN)
|
||||
err = gmath.FillBytes(m, ret)
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Sign implements the crypto.Signer interface
|
||||
func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
|
||||
if pssOpts, ok := opts.(*cryptoRSA.PSSOptions); ok {
|
||||
return cryptoRSA.SignPSS(rand, priv.Into(), pssOpts.Hash, digest, pssOpts)
|
||||
}
|
||||
|
||||
return SignPKCS1v15(rand, priv, sm.Hash{Hash: opts.HashFunc()}, digest)
|
||||
}
|
||||
|
||||
func (priv *PrivateKey) Public() crypto.PublicKey {
|
||||
return &priv.PublicKey
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package rsa
|
||||
|
||||
import (
|
||||
"xdx.jelly/xgcl/rsa/internal"
|
||||
"xdx.jelly/xgcl/sm"
|
||||
)
|
||||
|
||||
var PKCS1v15WithSha256Options = sm.SHA256
|
||||
var PKCS1v15WithSha1Options = sm.SHA1
|
||||
var PKCS1v15WithSm3Options = sm.SM3
|
||||
|
||||
// PrivateKey export internal.PrivateKey.
|
||||
type PrivateKey = internal.PrivateKey
|
||||
|
||||
// PublicKey export internal.PublicKey
|
||||
type PublicKey = internal.PublicKey
|
||||
|
||||
var NewPrivateKey = internal.NewPrivateKey
|
||||
var NewPublicKey = internal.NewPublicKey
|
||||
|
||||
var GenerateKey = internal.GenerateKey
|
||||
@@ -0,0 +1,247 @@
|
||||
package rsa
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
cryptoRSA "crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"xdx.jelly/xgcl/api/common"
|
||||
)
|
||||
|
||||
func BenchmarkKey(t *testing.B) {
|
||||
_, _, _ = PKCS1v15{}.GenerateKeyPairRSA(2048)
|
||||
}
|
||||
func TestKeyGen(t *testing.T) {
|
||||
|
||||
sk, pk, _ := PKCS1v15{}.GenerateKeyPairRSA(1024)
|
||||
fmt.Println(sk.D.Text(16))
|
||||
fmt.Println(pk.E)
|
||||
fmt.Println(pk.N.Text(16))
|
||||
}
|
||||
|
||||
func TestKey(t *testing.T) {
|
||||
sk, pk, _ := PKCS1v15{}.GenerateKeyPairRSA(2048)
|
||||
sk1 := sk
|
||||
pk1 := pk
|
||||
var sdfPriv common.RSArefPrivateKey
|
||||
var sdfPub common.RSArefPublicKey
|
||||
if err := sk.MarshalSDF(&sdfPriv); err != nil {
|
||||
t.Log("sk.MarshalSDF failed")
|
||||
t.Fail()
|
||||
}
|
||||
if err := sk.UnmarshalSDF(&sdfPriv); err != nil || sk != sk1 {
|
||||
t.Log("sk.UnmarshalSDF failed")
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if err := pk.MarshalSDF(&sdfPub); err != nil {
|
||||
t.Log("pk.MarshalSDF failed")
|
||||
t.Fail()
|
||||
}
|
||||
if err := pk.UnmarshalSDF(&sdfPub); err != nil || pk != pk1 {
|
||||
t.Log("pk.UnmarshalSDF failed")
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//RAW签摘要
|
||||
func TestRSARAWSign(t *testing.T) {
|
||||
// sha256摘要
|
||||
msg := []byte("message")
|
||||
digestData := sha256.Sum256(msg)
|
||||
|
||||
sk, pk, err := PKCS1v15{}.GenerateKeyPairRSA(2048)
|
||||
fmt.Printf("N:%s\n", sk.N.Text(16)) // sig is the same each time
|
||||
|
||||
// 签名值。2048bit integer
|
||||
signData, err := PKCS1v15{}.Sign(sk, crypto.SHA256, digestData[:])
|
||||
fmt.Printf("sig:%02x\n", signData) // sig is the same each time
|
||||
err = PKCS1v15{}.Verify(pk, crypto.SHA256, digestData[:], signData)
|
||||
if err != nil {
|
||||
t.Log("verify failed")
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func rsaRAWVerifyDigest(certPEM string, signData []byte, digestData []byte) error {
|
||||
block, _ := pem.Decode([]byte(certPEM))
|
||||
if block == nil {
|
||||
return fmt.Errorf("failed to decode certificate PEM")
|
||||
}
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse certificate PEM")
|
||||
}
|
||||
|
||||
if cert.PublicKeyAlgorithm != x509.RSA {
|
||||
return fmt.Errorf("not rsa algorithm")
|
||||
}
|
||||
|
||||
pk, ok := cert.PublicKey.(*cryptoRSA.PublicKey)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to get publickey")
|
||||
}
|
||||
|
||||
var hash crypto.Hash
|
||||
switch cert.SignatureAlgorithm {
|
||||
case x509.SHA1WithRSA:
|
||||
hash = crypto.SHA1
|
||||
case x509.SHA256WithRSA:
|
||||
hash = crypto.SHA256
|
||||
case x509.SHA384WithRSA:
|
||||
hash = crypto.SHA384
|
||||
case x509.SHA512WithRSA:
|
||||
hash = crypto.SHA512
|
||||
}
|
||||
|
||||
return PKCS1v15{}.Verify((&PublicKey{}).UnmarshalCryptoRsa(pk), hash, digestData, signData)
|
||||
}
|
||||
|
||||
//RAW验摘要
|
||||
func TestRSARAWVerifyDigest(t *testing.T) {
|
||||
digestData, _ := base64.StdEncoding.DecodeString("ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=")
|
||||
signData, _ := base64.StdEncoding.DecodeString("OkXl4owB9VncVmnUXSgQxwMwy8KVuFXk1e9vtOdrXEAOiAXbc6WYjmbT4tdoiEIj02ZaAT449QxQ2fkAsD4IP6iyrmP4Q34qlD5mbh3unuAchLW+XYuDFzVLMp2BLBw2aN/OmjaQdZo6GKy6h5RvrXgf+FwRwI1RIi4r+heA3mlnkUejSJXMkXsbamxMfTO+DH9GBv5cbSwLOEyGcnq/M7urIo/esZT5f+RXwIiI1Z+Qs+1UQ8WJ5O9oBgkJp4BY+o9oaEPuEIMsR0Hz94zv+9+CGn1G0xoBYVOxlRLWYsCyRYnwXzL/2jkJ3GAY3HQyiGa8WRB2LT+C2ijNK3D/nA==")
|
||||
certPEM := "MIIDiTCCAnGgAwIBAgIKb0XKECkuAA7e5jANBgkqhkiG9w0BAQsFADAlMRUwEwYDVQQDDAxBQkMgVEVTVCBDQTIxDDAKBgNVBAoMA0FCQzAeFw0xODA0MDIwMDQ4MzFaFw0yMzA0MDIwMDQ4MzFaME4xLzAtBgNVBAMMJjQ0OTk0NDIxMzAwLjAwMDUuMDAwMC42NjQ0NTAyNTY2MjY5NTAxMQ0wCwYDVQQLDARVd2luMQwwCgYDVQQKDANBQkMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCHbgJr3CmQf69XOK27F4V3YDCfvnH2JcL4xDxHd2B2Sy29NeU4bFsCZaBTc2N3ujHTLSRn+NEuFE90aejd/TvvuDzKda0r0615wo5NUfQiY5pi7UQ3k1IXtSpuImlIdPhnS0egBHropMQgd1f1K+54bSWB9+vhCIATP9GDQS32fJ2z3If0E3T5fCKiS4KS+SBhwtvEEMisCbDpD2y+BwYz0Ozkth9SrJ6r+ujLGwu5JYD/YRL7or8lpi575KvT6Ahf0iDZ/bzLjyZ5rWjSAWWAPJCjUoOFDt9XhY5fTo4B0lj6RV96qyCIau8n+fSVIiqXfxK5/W+iHj9zTXfe2sNbAgMBAAGjgZEwgY4wHwYDVR0jBBgwFoAUErtyLm5Iqy6z01KtzsJ33EmoKtIwCQYDVR0TBAIwADBBBgNVHR8EOjA4MDagNKAypDAwLjEQMA4GA1UEAwwHY3JsNDQ5MjEMMAoGA1UECwwDY3JsMQwwCgYDVQQKDANBQkMwHQYDVR0OBBYEFAHfn4lC2TqykHQ9dIhle8y1d7TyMA0GCSqGSIb3DQEBCwUAA4IBAQAwjLw04jTEDh06UepD7pjmH7rcmqOeXMsfPRLPF1vG2w8dOAvwH7fUIRYWKx4i9uM/mue5rYZokP5p8bV/Gx1+KNEEK7LOgUKlHjc5U/HVa89SnynWCUs9tD1DDM25BSb9szzwUz0QG5XNgskn7h3LsXoUdzXV+j+eIYuIY3q/TURN/3ds7if+0zwnaFwj9PpUcB3A9ShynhpZX6xBLMH3WT8MofUdzVmvZDPxaGxBpORQL8ZlXdU34aeHX9290lBTqH3TxXXEuWoBfzW2cp0j5daoGh9VX7Qh93d3mj+vZKv/W6B0GmNfEiABCNUrN1x4nz7jK1yyMu1j9rJTSXOQ"
|
||||
certPEM = "-----BEGIN CERTIFICATE-----\n" + certPEM + "\n-----END CERTIFICATE-----"
|
||||
err := rsaRAWVerifyDigest(certPEM, signData, digestData)
|
||||
if err != nil {
|
||||
t.Log("verify failed")
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpeed(t *testing.T) {
|
||||
msg := []byte("message")
|
||||
digestData := sha256.Sum256(msg)
|
||||
|
||||
sk, pk, _ := PKCS1v15{}.GenerateKeyPairRSA(2048)
|
||||
// sk.Precompute()
|
||||
var signData []byte
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
signData, _ = PKCS1v15{}.Sign(sk, crypto.SHA256, digestData[:])
|
||||
}
|
||||
|
||||
cnt := 1000
|
||||
start := time.Now()
|
||||
for i := 0; i < cnt; i++ {
|
||||
signData, _ = PKCS1v15{}.Sign(sk, crypto.SHA256, digestData[:])
|
||||
}
|
||||
end := time.Now()
|
||||
elapsed := end.Sub(start)
|
||||
fmt.Printf("Sign %d, used time: %d ms, %d pcs/s\n", cnt, elapsed.Milliseconds(), int(float64(cnt)/float64(elapsed.Milliseconds())*1000))
|
||||
|
||||
start = time.Now()
|
||||
for i := 0; i < cnt; i++ {
|
||||
_ = PKCS1v15{}.Verify(pk, crypto.SHA256, digestData[:], signData)
|
||||
}
|
||||
end = time.Now()
|
||||
elapsed = end.Sub(start)
|
||||
fmt.Printf("verify %d, used time: %d ms, %d pcs/s\n", cnt, elapsed.Milliseconds(), int(float64(cnt)/float64(elapsed.Milliseconds())*1000))
|
||||
|
||||
}
|
||||
|
||||
func BenchmarkSign(b *testing.B) {
|
||||
msg := []byte("message")
|
||||
digestData := sha256.Sum256(msg)
|
||||
|
||||
sk, _, _ := PKCS1v15{}.GenerateKeyPairRSA(1024 * 2)
|
||||
b.StartTimer()
|
||||
_, _ = PKCS1v15{}.Sign(sk, crypto.SHA256, digestData[:])
|
||||
b.StopTimer()
|
||||
}
|
||||
|
||||
func BenchmarkVerify(b *testing.B) {
|
||||
msg := []byte("message")
|
||||
digestData := sha256.Sum256(msg)
|
||||
|
||||
sk, pk, _ := PKCS1v15{}.GenerateKeyPairRSA(2048)
|
||||
signData, _ := PKCS1v15{}.Sign(sk, crypto.SHA256, digestData[:])
|
||||
b.StartTimer()
|
||||
|
||||
_ = PKCS1v15{}.Verify(pk, crypto.SHA256, digestData[:], signData)
|
||||
b.StopTimer()
|
||||
}
|
||||
|
||||
func TestRsaSdf(t *testing.T) {
|
||||
impl := PKCS1v15{}
|
||||
|
||||
sk, pk, err := impl.GenerateKeyPairRSA(2048)
|
||||
if err != nil || sk.Validate() != nil {
|
||||
t.Log("GenerateKeyPairRSA failed")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
envelopedKeyPair, err := impl.GenerateEnvelopedKeyPairRSA(1024, pk)
|
||||
if err != nil {
|
||||
t.Log("GenerateEnvelopedKeyPairRSA failed")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
sk1, pk1, err := impl.ImportEnvelopedKeyPairRSA(envelopedKeyPair, sk)
|
||||
if err != nil || sk1.Validate() != nil {
|
||||
t.Log("ImportEnvelopedKeyPairRSA failed", err)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
sessionKey, encryptedSessionKey, err := impl.GenerateKeyRSA(16, pk)
|
||||
if err != nil {
|
||||
t.Log("GenerateKeyRSA failed")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
encryptedSessionKey, err = impl.ExchangeDigitEnvelopeRSA(sk, pk1, encryptedSessionKey)
|
||||
if err != nil {
|
||||
t.Log("ExchangeDigitEnvelopeRSA failed")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
decrytpedSessionKey, err := impl.ImportKeyRSA(16, sk1, encryptedSessionKey)
|
||||
if err != nil {
|
||||
t.Log("ImportKeyRSA failed")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
if bytes.Compare(sessionKey, decrytpedSessionKey) != 0 {
|
||||
t.Log("sessionkey not equal")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
data := make([]byte, pk.Size())
|
||||
data[0] = 1
|
||||
encryptedData, err := impl.PublicKeyOperationRSA(pk, data)
|
||||
if err != nil {
|
||||
t.Log("PublicKeyOperationRSA failed")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
decryptedData, err := impl.PrivateKeyOperationRSA(sk, encryptedData)
|
||||
if err != nil {
|
||||
t.Log("PrivateKeyOperationRSA failed")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
if bytes.Compare(data, decryptedData) != 0 {
|
||||
t.Log("PublicKeyOperationRSA/PrivateKeyOperationRSA failed")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
package rsa
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/api/common"
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/identifier"
|
||||
"xdx.jelly/xgcl/rsa/internal"
|
||||
"xdx.jelly/xgcl/sm/sm4"
|
||||
)
|
||||
|
||||
// GenerateKeyPairRSA corresponding to SDF_GenerateKeyPair_RSA
|
||||
func (PKCS1v15) GenerateKeyPairRSA(keyBits uint32) (*PrivateKey, *PublicKey, error) {
|
||||
if keyBits > common.RSAref_MAX_BITS {
|
||||
return nil, nil, common.SDR_KEYERR
|
||||
}
|
||||
privateKey, err := internal.GenerateKey(grand.Reader, int(keyBits))
|
||||
// privateKey, err := internal.GenerateKey(rand.New(rand.NewSource(1234)), int(keyBits))
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, common.SDR_KEYERR
|
||||
}
|
||||
|
||||
return privateKey, &privateKey.PublicKey, nil
|
||||
}
|
||||
|
||||
// GenerateEnvelopedKeyPairRSA 生成密钥对保护结构并用publicKey加密输出。
|
||||
// 对应SDF_GenerateRSAKeyPairWithIPK_RSA和SDF_GenerateRSAKeyPairWithEPK_RSA
|
||||
// 注意:内部不检查keyBits.
|
||||
func (p PKCS1v15) GenerateEnvelopedKeyPairRSA(keyBits uint32, publicKey *PublicKey) (*common.EnvelopedRSAKey, error) {
|
||||
sm4key := make([]byte, sm4.BlockSize)
|
||||
n, err := grand.GenerateRandom(sm4key)
|
||||
if n < sm4.BlockSize || err != nil {
|
||||
return nil, common.SDR_RANDERR
|
||||
}
|
||||
|
||||
sk, pk, err := p.GenerateKeyPairRSA(keyBits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
enveloped := common.EnvelopedRSAKey{
|
||||
SymmAlgID: identifier.SGDSM4ECB,
|
||||
Bits: keyBits,
|
||||
}
|
||||
|
||||
var data [common.RSAref_MAX_LEN]byte
|
||||
buf := data[:]
|
||||
buf0 := data[:common.RSAref_MAX_PLEN]
|
||||
|
||||
gmath.FillBytes(sk.N, buf)
|
||||
copy(enveloped.EncryptedPriKey[0][:], buf[:common.RSAref_MAX_PLEN])
|
||||
copy(enveloped.EncryptedPriKey[1][:], buf[common.RSAref_MAX_PLEN:])
|
||||
|
||||
gmath.FillBytes(new(big.Int).SetInt64(int64(sk.E)), buf)
|
||||
copy(enveloped.EncryptedPriKey[2][:], buf[:common.RSAref_MAX_PLEN])
|
||||
copy(enveloped.EncryptedPriKey[3][:], buf[common.RSAref_MAX_PLEN:])
|
||||
|
||||
gmath.FillBytes(sk.D, buf)
|
||||
copy(enveloped.EncryptedPriKey[4][:], buf[:common.RSAref_MAX_PLEN])
|
||||
copy(enveloped.EncryptedPriKey[5][:], buf[common.RSAref_MAX_PLEN:])
|
||||
|
||||
if len(sk.Primes) != 2 {
|
||||
return nil, common.SDR_KEYERR
|
||||
}
|
||||
gmath.FillBytes(sk.Primes[0], buf0)
|
||||
copy(enveloped.EncryptedPriKey[6][:], buf0)
|
||||
gmath.FillBytes(sk.Primes[1], buf0)
|
||||
copy(enveloped.EncryptedPriKey[7][:], buf0)
|
||||
|
||||
gmath.FillBytes(sk.Precomputed.Dp, buf0)
|
||||
copy(enveloped.EncryptedPriKey[8][:], buf0)
|
||||
|
||||
gmath.FillBytes(sk.Precomputed.Dq, buf0)
|
||||
copy(enveloped.EncryptedPriKey[9][:], buf0)
|
||||
|
||||
gmath.FillBytes(sk.Precomputed.Qinv, buf0)
|
||||
copy(enveloped.EncryptedPriKey[10][:], buf0)
|
||||
|
||||
for i := 0; i < len(enveloped.EncryptedPriKey); i++ {
|
||||
sm4.EncryptECB(enveloped.EncryptedPriKey[i][:], sm4key, enveloped.EncryptedPriKey[i][:])
|
||||
}
|
||||
|
||||
err = pk.MarshalSDF(&enveloped.PubKey)
|
||||
if err != nil {
|
||||
return nil, common.SDR_UNKNOWERR
|
||||
}
|
||||
|
||||
C, err := internal.EncryptPKCS1v15(grand.Reader, publicKey, sm4key)
|
||||
if err != nil {
|
||||
return nil, common.SDR_KEYERR
|
||||
}
|
||||
enveloped.L = uint32(len(C))
|
||||
copy(enveloped.C[:], C)
|
||||
return &enveloped, nil
|
||||
}
|
||||
|
||||
// ImportEnvelopedKeyPairRSA 导入RSA密钥保护结构。
|
||||
func (PKCS1v15) ImportEnvelopedKeyPairRSA(envelopedRSAKey *common.EnvelopedRSAKey, privateKey *PrivateKey) (*PrivateKey, *PublicKey, error) {
|
||||
sk := internal.NewPrivateKey()
|
||||
|
||||
sm4key, err := internal.DecryptPKCS1v15(grand.Reader, privateKey, envelopedRSAKey.C[:envelopedRSAKey.L])
|
||||
if err != nil || len(sm4key) != sm4.BlockSize {
|
||||
return nil, nil, common.SDR_INARGERR
|
||||
}
|
||||
for i := 0; i < len(envelopedRSAKey.EncryptedPriKey); i++ {
|
||||
sm4.DecryptECB(envelopedRSAKey.EncryptedPriKey[i][:], sm4key, envelopedRSAKey.EncryptedPriKey[i][:])
|
||||
}
|
||||
|
||||
var data [common.RSAref_MAX_LEN]byte
|
||||
buf := data[:]
|
||||
|
||||
copy(buf[:common.RSAref_MAX_PLEN], envelopedRSAKey.EncryptedPriKey[0][:])
|
||||
copy(buf[common.RSAref_MAX_PLEN:], envelopedRSAKey.EncryptedPriKey[1][:])
|
||||
sk.N.SetBytes(buf)
|
||||
|
||||
copy(buf[:common.RSAref_MAX_PLEN], envelopedRSAKey.EncryptedPriKey[2][:])
|
||||
copy(buf[common.RSAref_MAX_PLEN:], envelopedRSAKey.EncryptedPriKey[3][:])
|
||||
sk.E = int(new(big.Int).SetBytes(buf).Int64())
|
||||
|
||||
copy(buf[:common.RSAref_MAX_PLEN], envelopedRSAKey.EncryptedPriKey[4][:])
|
||||
copy(buf[common.RSAref_MAX_PLEN:], envelopedRSAKey.EncryptedPriKey[5][:])
|
||||
sk.D.SetBytes(buf)
|
||||
|
||||
sk.Primes[0].SetBytes(envelopedRSAKey.EncryptedPriKey[6][:])
|
||||
sk.Primes[1].SetBytes(envelopedRSAKey.EncryptedPriKey[7][:])
|
||||
sk.Precompute()
|
||||
|
||||
return sk, &sk.PublicKey, nil
|
||||
}
|
||||
|
||||
// GenerateKeyRSA 生成会话密钥并用publicKey加密输出
|
||||
func (PKCS1v15) GenerateKeyRSA(keyBits uint32, publicKey *PublicKey) ([]byte, []byte, error) {
|
||||
key := make([]byte, keyBits)
|
||||
c, err := internal.EncryptPKCS1v15(grand.Reader, publicKey, key)
|
||||
if err != nil {
|
||||
return nil, nil, common.SDR_KEYERR
|
||||
}
|
||||
return key, c, nil
|
||||
}
|
||||
|
||||
// GenerateKeyRSA 导入会话密钥密文encryptedKey,并用privateKey解密。返回会话密钥。
|
||||
func (PKCS1v15) ImportKeyRSA(keyBits uint32, privateKey *PrivateKey, encryptedKey []byte) ([]byte, error) {
|
||||
key, err := internal.DecryptPKCS1v15(grand.Reader, privateKey, encryptedKey)
|
||||
if err != nil || len(key) != int(keyBits) {
|
||||
return nil, common.SDR_INARGERR
|
||||
}
|
||||
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// ExchangeDigitEnvelopeRSA 基于RSA的数字信封转换,privateKey解密会话密钥密文,再用publicKey加密会话密文。
|
||||
// inKey: 输入会话密钥密文
|
||||
// 返回: 转换后的会话密文
|
||||
func (PKCS1v15) ExchangeDigitEnvelopeRSA(privateKey *PrivateKey, publicKey *PublicKey, inKey []byte) ([]byte, error) {
|
||||
key, err := internal.DecryptPKCS1v15(grand.Reader, privateKey, inKey)
|
||||
if err != nil {
|
||||
return nil, common.SDR_INARGERR
|
||||
}
|
||||
|
||||
c, err := internal.EncryptPKCS1v15(grand.Reader, publicKey, key)
|
||||
if err != nil {
|
||||
return nil, common.SDR_KEYERR
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// PublicKeyOperationRSA RSA公钥运算。数据格式由应用层封装。inData 应该小于 privateKey.Size()
|
||||
func (PKCS1v15) PublicKeyOperationRSA(publicKey *PublicKey, inData []byte) ([]byte, error) {
|
||||
|
||||
return internal.PublicKeyOperationRSA(publicKey, inData)
|
||||
}
|
||||
|
||||
// PrivateKeyOperationRSA RSA私钥运算。数据格式由应用层封装。inData 应该小于 privateKey.Bits/8
|
||||
func (PKCS1v15) PrivateKeyOperationRSA(privateKey *PrivateKey, inData []byte) ([]byte, error) {
|
||||
return internal.PrivateKeyOperationRSA(privateKey, inData)
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package rsa
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
|
||||
"xdx.jelly/xgcl/rsa/internal"
|
||||
"xdx.jelly/xgcl/sm"
|
||||
)
|
||||
|
||||
var VerifyPKCS1v15 = internal.VerifyPKCS1v15
|
||||
var SignPKCS1v15 = internal.SignPKCS1v15
|
||||
|
||||
// helper function for RSA_SM3 signature
|
||||
|
||||
// SignPKCS1v15WithSm3 signature with SM3
|
||||
func SignPKCS1v15WithSm3(priv *PrivateKey, hashed []byte) ([]byte, error) {
|
||||
return SignPKCS1v15(nil, priv, sm.SM3, hashed)
|
||||
}
|
||||
|
||||
// SignPKCS1v15WithSm3 signature with SHA256
|
||||
func SignPKCS1v15WithSha256(priv *PrivateKey, hashed []byte) ([]byte, error) {
|
||||
return SignPKCS1v15(nil, priv, sm.SHA256, hashed)
|
||||
}
|
||||
|
||||
// VerifyPKCS1v15WithSm3 verify with SM3
|
||||
func VerifyPKCS1v15WithSm3(pub *PublicKey, hashed []byte, sig []byte) error {
|
||||
return VerifyPKCS1v15(pub, sm.SM3, hashed, sig)
|
||||
}
|
||||
|
||||
// VerifyPKCS1v15WithSha256 verify with SHA256
|
||||
func VerifyPKCS1v15WithSha256(pub *PublicKey, hashed []byte, sig []byte) error {
|
||||
return VerifyPKCS1v15(pub, sm.SHA256, hashed, sig)
|
||||
}
|
||||
|
||||
// PKCS1v15 implement the sdf.RSAAdapter interface
|
||||
type PKCS1v15 struct{}
|
||||
|
||||
// 0018用的是PKCS1v1.5 还有其他暂不实现
|
||||
func NewPKCS1v15() PKCS1v15 {
|
||||
return PKCS1v15{}
|
||||
}
|
||||
|
||||
func (PKCS1v15) Sign(priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
|
||||
return internal.SignPKCS1v15(nil, priv, sm.Hash{Hash: hash}, hashed)
|
||||
}
|
||||
|
||||
func (PKCS1v15) Verify(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error {
|
||||
return internal.VerifyPKCS1v15(pub, sm.Hash{Hash: hash}, hashed, sig)
|
||||
}
|
||||
Reference in New Issue
Block a user