//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 }