131 lines
2.9 KiB
Go
131 lines
2.9 KiB
Go
//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
|
|
}
|