init: v1.0.0
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
|
||||
package paillier
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm4"
|
||||
)
|
||||
|
||||
func TestEnv(t *testing.T) {
|
||||
sk, pk, err := GenerateKey(2048)
|
||||
assert.Nil(t, err)
|
||||
for i := 0; i < 1000; i++ {
|
||||
kek := grand.GetRandom(16) //[]byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
|
||||
|
||||
mykey := grand.GetRandom(16)
|
||||
mykeyPaillierCipher, err := EncryptKey(mykey, pk)
|
||||
assert.Nil(t, err)
|
||||
|
||||
iv, mykeyEnvelopeCipher, err := GenEnvelope(mykeyPaillierCipher, kek, pk)
|
||||
assert.Nil(t, err)
|
||||
|
||||
mykeyEnvelope, err := DecryptEnvelope(mykeyEnvelopeCipher, sk) // mykeyEnvelope = SM4CTREnc(kek, mykey) = sm4.Enc(kek, iv) ^ key
|
||||
assert.Nil(t, err)
|
||||
|
||||
// recover mykey from mykeyEnvelope
|
||||
|
||||
mykey2 := DecryptKey(iv []byte, keyEnvelope []byte, pk *PublicKey)
|
||||
|
||||
// check
|
||||
key2, err := sm4.EncryptECB(nil, kek, iv)
|
||||
assert.Nil(t, err)
|
||||
|
||||
for i := range key2 {
|
||||
key2[i] ^= ctrEncKey[i]
|
||||
}
|
||||
assert.Equal(t, key, key2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncKey(t *testing.T) {
|
||||
key := grand.GetRandom(128)
|
||||
|
||||
sk, pk, err := GenerateKey(2048)
|
||||
assert.Nil(t, err)
|
||||
|
||||
c, err := EncryptKey(key, pk)
|
||||
assert.Nil(t, err)
|
||||
|
||||
key2, err := DecryptKey(c, 128, sk)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, key, key2)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
package paillier
|
||||
|
||||
// envelope provide hybrid encryption for a user with a remote cryptographic server.
|
||||
// The server has a KEK and the user wants to encrypt a file.
|
||||
// 1. The user generate a random user key ukey
|
||||
// 2. The user use ukey to encrypt the file
|
||||
// 3. The user do the followings to encrypt the ukey with KEK without leaking ukey to the server:
|
||||
// 3-0. The user generate a (temporary or long term) paillier key pair (sk, pk).
|
||||
// 3-1. The user encrypt ukey with paillier encryption: ukeyCipher = PaiEnc(ukey, pk)
|
||||
// 3-2. The server HOMOMORPHICLY encrypt ukey with KEK: ukeyEnvelopeCipher = PaiEnc(SM4Enc(ukey, KEK), pk)
|
||||
// 3-3. The user decrypt ukeyEnvelopeCipher and get ukeyEnvelope = SM4Enc(ukey, KEK)
|
||||
//
|
||||
// The user do the following to decrypt the ukey and then to decrypt the file.
|
||||
// Also without leaking ukey.
|
||||
// 1. The user generate a (temporary or long term) paillier key pair (sk, pk).
|
||||
// 2. User encrypt ukeyEnvelope: ukeyEnvelopeCipher = PaiEnc(ukeyEnvelope, pk)
|
||||
// 3. The server HOMORPHICLY decrypt ukeyEnvelopeCipher: ukeyCipher = PaiEnc(ukey, pk)
|
||||
// 4. The user decrypt ukeyCipher, with ukey.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm4"
|
||||
)
|
||||
|
||||
// xyzw => 0x0y0z0w
|
||||
var tbl = []byte{0, 1, 4, 5, 16, 17, 20, 21, 64, 65, 68, 69, 80, 81, 84, 85}
|
||||
|
||||
type EnvelopeUser struct{}
|
||||
type EnvelopeServer struct{}
|
||||
|
||||
// EncryptUserKey
|
||||
func (EnvelopeUser) EncryptUserKey(ukey []byte, pk *PublicKey) (ukeyCipher *Cipher, err error) {
|
||||
if len(ukey)*8*2 > pk.Bits() {
|
||||
return nil, fmt.Errorf("input key too long, should less than %d bytes", pk.Bits()/8/2)
|
||||
}
|
||||
buf := make([]byte, 0, len(ukey)*2)
|
||||
for _, k := range ukey {
|
||||
buf = append(buf, tbl[k&0xf])
|
||||
buf = append(buf, tbl[k>>4])
|
||||
}
|
||||
return pk.Encrypt(new(big.Int).SetBytes(buf), grand.Reader)
|
||||
}
|
||||
|
||||
func DecryptKey(c *Cipher, keyLength int, priKey *PrivateKey) ([]byte, error) {
|
||||
k, err := priKey.Decrypt(c)
|
||||
_ = err
|
||||
key2 := make([]byte, keyLength*2)
|
||||
k.FillBytes(key2)
|
||||
key := make([]byte, keyLength)
|
||||
for i := 0; i < len(key); i++ {
|
||||
x := key2[2*i]
|
||||
y := key2[2*i+1]
|
||||
n := byte(0)
|
||||
n |= (x >> 0) & 1
|
||||
n |= (x >> 1) & 2
|
||||
n |= (x >> 2) & 4
|
||||
n |= (x >> 3) & 8
|
||||
key[i] = n
|
||||
|
||||
n = byte(0)
|
||||
n |= (y >> 0) & 1
|
||||
n |= (y >> 1) & 2
|
||||
n |= (y >> 2) & 4
|
||||
n |= (y >> 3) & 8
|
||||
key[i] |= (n << 4)
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func GenEnvelope(c0 *Cipher, kek []byte, pubkey *PublicKey) ([]byte, *Cipher, error) {
|
||||
iv := grand.GetRandom(16)
|
||||
c1, err := sm4.EncryptECB(nil, kek, iv) // c1 = sm4.Enc(iv)
|
||||
c2, err := EncryptUserKey(c1, pubkey) // c2 = PaiEnc(sm4.Enc(iv))
|
||||
c2.HomomorphicAdd(c2, c0, pubkey) // c2 = PaiEnc(sm4.Enc(iv) ^ key)
|
||||
|
||||
_ = err
|
||||
return iv, c2, nil
|
||||
}
|
||||
|
||||
func DecryptEnvelope(c *Cipher, prikey *PrivateKey) ([]byte, error) {
|
||||
k, err := prikey.Decrypt(c)
|
||||
_ = err
|
||||
key2 := make([]byte, 32)
|
||||
k.FillBytes(key2)
|
||||
key := make([]byte, 16)
|
||||
for i := 0; i < 16; i++ {
|
||||
x := key2[2*i]
|
||||
y := key2[2*i+1]
|
||||
n := byte(0)
|
||||
n |= (x >> 0) & 1
|
||||
n |= (x >> 1) & 2
|
||||
n |= (x >> 2) & 4
|
||||
n |= (x >> 3) & 8
|
||||
key[i] = n
|
||||
|
||||
n = byte(0)
|
||||
n |= (y >> 0) & 1
|
||||
n |= (y >> 1) & 2
|
||||
n |= (y >> 2) & 4
|
||||
n |= (y >> 3) & 8
|
||||
key[i] |= (n << 4)
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
@@ -0,0 +1,363 @@
|
||||
package paillier
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"sync"
|
||||
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
"golang.org/x/crypto/cryptobyte/asn1"
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/pbkd"
|
||||
)
|
||||
|
||||
//
|
||||
// PublicKey ::= INTEGER
|
||||
//
|
||||
// PrivateKey ::= SEQUENCE{
|
||||
// lambda INTEGER,
|
||||
// N INTEGER
|
||||
// }
|
||||
//
|
||||
// Cipher ::= INTEGER
|
||||
|
||||
type PublicKey struct {
|
||||
N *big.Int
|
||||
N2 *big.Int
|
||||
|
||||
mu sync.Mutex // guard rn
|
||||
rn *big.Int
|
||||
}
|
||||
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
lambda *big.Int
|
||||
|
||||
// option
|
||||
lambdaInv *big.Int
|
||||
p, q *big.Int
|
||||
}
|
||||
|
||||
func (k *PrivateKey) Public() *PublicKey {
|
||||
if k.PublicKey.N2 == nil {
|
||||
k.PublicKey.N2 = new(big.Int).Mul(k.PublicKey.N, k.PublicKey.N)
|
||||
}
|
||||
if k.rn == nil {
|
||||
k.Precompute(grand.Reader)
|
||||
}
|
||||
return &k.PublicKey
|
||||
}
|
||||
|
||||
// Cipher the member variable D is for gcl's internal use.
|
||||
// You should never use it except you know what you're doing.
|
||||
type Cipher struct {
|
||||
D *big.Int
|
||||
}
|
||||
|
||||
func newPrivateKey(p *big.Int, q *big.Int) *PrivateKey {
|
||||
sk := &PrivateKey{
|
||||
PublicKey: PublicKey{
|
||||
N: new(big.Int).Mul(p, q),
|
||||
},
|
||||
lambda: new(big.Int),
|
||||
lambdaInv: new(big.Int),
|
||||
}
|
||||
pk := sk.Public()
|
||||
|
||||
// lambda = LCM(p-1, q-1) or just (p-1)*(q-1)
|
||||
// lcm(sk.lambda, new(big.Int).Sub(p, gmath.BigInt1), new(big.Int).Sub(q, gmath.BigInt1))
|
||||
sk.lambda.Mul(new(big.Int).Sub(p, gmath.BigInt1), new(big.Int).Sub(q, gmath.BigInt1))
|
||||
|
||||
sk.lambdaInv.ModInverse(sk.lambda, pk.N)
|
||||
return sk
|
||||
}
|
||||
|
||||
// return l = lcm(a,b)
|
||||
func lcm(l, a, b *big.Int) {
|
||||
d := new(big.Int).GCD(nil, nil, a, b)
|
||||
l.Mul(a, b)
|
||||
l.Div(l, d)
|
||||
}
|
||||
|
||||
// GenerateKey 生成同态密钥. bits 应为2048.
|
||||
// rnd_opt 可选, 忽略则使用grand.Reader.
|
||||
func GenerateKey(bits int, rnd_opt ...io.Reader) (*PrivateKey, *PublicKey, error) {
|
||||
var rnd io.Reader
|
||||
if len(rnd_opt) > 0 {
|
||||
rnd = rnd_opt[0]
|
||||
} else {
|
||||
rnd = grand.Reader
|
||||
}
|
||||
|
||||
priKey := &PrivateKey{}
|
||||
rsaKey, err := rsa.GenerateKey(rnd, bits)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
priKey = newPrivateKey(rsaKey.Primes[0], rsaKey.Primes[1])
|
||||
|
||||
return priKey, &priKey.PublicKey, nil
|
||||
}
|
||||
|
||||
func (k *PrivateKey) Decrypt(c *Cipher) (*big.Int, error) {
|
||||
if c.D == nil || c.D.Cmp(k.N2) >= 0 {
|
||||
return nil, errors.New("invalid cipher")
|
||||
}
|
||||
if k.lambdaInv == nil {
|
||||
k.lambdaInv = new(big.Int).ModInverse(k.lambda, k.N)
|
||||
}
|
||||
pk := k.Public()
|
||||
d := c.D
|
||||
L := new(big.Int)
|
||||
L.Exp(d, k.lambda, pk.N2) // L = c^lambda mod n^2
|
||||
L.Sub(L, gmath.BigInt1)
|
||||
L.Div(L, pk.N) // L = (c^lambda - 1)/n
|
||||
L.Mul(L, k.lambdaInv)
|
||||
L.Mod(L, pk.N)
|
||||
return L, nil
|
||||
}
|
||||
func (k *PublicKey) Bits() int {
|
||||
return k.N.BitLen()
|
||||
}
|
||||
|
||||
// Precompute computes r^N mod N^2 for a random r.
|
||||
func (k *PublicKey) Precompute(rnd io.Reader) error {
|
||||
if k.rn != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
k.mu.Lock()
|
||||
defer k.mu.Unlock()
|
||||
|
||||
if k.N2 == nil {
|
||||
k.N2 = new(big.Int).Mul(k.N, k.N)
|
||||
}
|
||||
|
||||
if k.rn != nil {
|
||||
return nil
|
||||
}
|
||||
buf := make([]byte, k.N.BitLen()/2)
|
||||
_, err := rnd.Read(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf[0] |= 1 // at least one
|
||||
r := new(big.Int).SetBytes(buf)
|
||||
r.Exp(r, k.N, k.N2) // r = r^n mod n^2
|
||||
k.rn = r
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *PublicKey) Encrypt(m *big.Int, rnd io.Reader) (*Cipher, error) {
|
||||
if true {
|
||||
k.Precompute(grand.Reader)
|
||||
rn := new(big.Int).SetBytes(grand.GetRandom(12))
|
||||
rn.Exp(k.rn, rn, k.N2)
|
||||
|
||||
d := new(big.Int)
|
||||
d.Mul(k.N, m) // d = n * m
|
||||
d.Add(d, gmath.BigInt1) // d = nm + 1
|
||||
|
||||
d.Mul(d, rn) // c = (nm+1)*r^n mod n^2
|
||||
d.Mod(d, k.N2)
|
||||
return &Cipher{D: d}, nil
|
||||
} else {
|
||||
// r should select from (1, N)
|
||||
var r *big.Int
|
||||
var err error
|
||||
for {
|
||||
r, err = rand.Int(rnd, k.N)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// should we check gcd(r,n) == 1?
|
||||
if r.Sign() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d := new(big.Int)
|
||||
d.Mul(k.N, m) // d = n * m
|
||||
d.Add(d, gmath.BigInt1) // d = nm + 1
|
||||
|
||||
r.Exp(r, k.N, k.N2) // r = r^n mod n^2
|
||||
// r.SetUint64(1)
|
||||
d.Mul(d, r) // c = (nm+1)*r^n mod n^2
|
||||
d.Mod(d, k.N2)
|
||||
return &Cipher{D: d}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func Encrypt(m *big.Int, publicKey *PublicKey, rnd io.Reader) (*Cipher, error) {
|
||||
return publicKey.Encrypt(m, rnd)
|
||||
}
|
||||
|
||||
func Decrypt(c *Cipher, key *PrivateKey) (*big.Int, error) {
|
||||
return key.Decrypt(c)
|
||||
}
|
||||
|
||||
func GenerateKeyFromPassword(bits int, password []byte, salt []byte, count int) (*PrivateKey, error) {
|
||||
b, err := pbkd.PbkdfWithHmacSm3(password, salt, count, int64((bits+15)/16))
|
||||
pBits := bits / 2
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p := big.NewInt(0).SetBytes(b)
|
||||
p.SetBit(p, 0, 1)
|
||||
p.SetBit(p, pBits-1, 1)
|
||||
for !p.ProbablyPrime(20) {
|
||||
p.Add(p, big.NewInt(2))
|
||||
}
|
||||
|
||||
b, err = pbkd.PbkdfWithHmacSm3(password, salt, count+1, int64(bits/16))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q := big.NewInt(0).SetBytes(b)
|
||||
q.SetBit(q, 0, 1)
|
||||
q.SetBit(q, pBits-1, 1)
|
||||
for !q.ProbablyPrime(20) || q.Cmp(p) == 0 {
|
||||
q.Add(q, big.NewInt(2))
|
||||
}
|
||||
return newPrivateKey(p, q), nil
|
||||
}
|
||||
|
||||
func (c *Cipher) Marshal() ([]byte, error) {
|
||||
if c.D == nil {
|
||||
return nil, errors.New("empty cipher")
|
||||
}
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BigInt(c.D)
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func (c *Cipher) Unmarshal(b []byte) error {
|
||||
if c.D == nil {
|
||||
c.D = new(big.Int)
|
||||
}
|
||||
input := cryptobyte.String(b)
|
||||
if !input.ReadASN1Integer(c.D) {
|
||||
return errors.New("parse ASN.1 cipher failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// round up n to the nearest power of 2.
|
||||
func roundup(n uint64) uint64 {
|
||||
n--
|
||||
n |= n >> 1
|
||||
n |= n >> 2
|
||||
n |= n >> 4
|
||||
n |= n >> 8
|
||||
n |= n >> 16
|
||||
n |= n >> 32
|
||||
return n + 1
|
||||
}
|
||||
|
||||
func (k *PublicKey) Size() uint {
|
||||
return uint(roundup(uint64(k.N.BitLen())))
|
||||
}
|
||||
|
||||
// Marshal 编码公钥, PublicKey ::= INTEGER
|
||||
func (k *PublicKey) Marshal() ([]byte, error) {
|
||||
if k.N == nil {
|
||||
return nil, errors.New("empty public key")
|
||||
}
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BigInt(k.N)
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func (k *PublicKey) Unmarshal(b []byte) error {
|
||||
if k.N == nil || k.N2 == nil {
|
||||
k.N = new(big.Int)
|
||||
k.N2 = new(big.Int)
|
||||
}
|
||||
|
||||
input := cryptobyte.String(b)
|
||||
if !input.ReadASN1Integer(k.N) {
|
||||
return errors.New("parse ASN.1 public key failed")
|
||||
}
|
||||
|
||||
k.N2.Mul(k.N, k.N)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalExt 编码公钥,包括预计算数据, PublicKey ::= INTEGER
|
||||
func (k *PublicKey) MarshalExt() ([]byte, error) {
|
||||
if k.N == nil {
|
||||
return nil, errors.New("empty public key")
|
||||
}
|
||||
k.Precompute(grand.Reader)
|
||||
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
|
||||
b.AddASN1BigInt(k.N)
|
||||
b.AddASN1BigInt(k.rn)
|
||||
})
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func (k *PublicKey) UnmarshalExt(b []byte) error {
|
||||
if k.N == nil || k.N2 == nil {
|
||||
k.N = new(big.Int)
|
||||
k.N2 = new(big.Int)
|
||||
}
|
||||
if k.rn == nil {
|
||||
k.rn = new(big.Int)
|
||||
}
|
||||
|
||||
input := cryptobyte.String(b)
|
||||
var inner cryptobyte.String
|
||||
if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
|
||||
!inner.ReadASN1Integer(k.N) ||
|
||||
!inner.ReadASN1Integer(k.rn) {
|
||||
return errors.New("read ASN.1 private key failed")
|
||||
}
|
||||
|
||||
k.N2.Mul(k.N, k.N)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal 编码私钥
|
||||
func (k *PrivateKey) Marshal() ([]byte, error) {
|
||||
if k.lambda == nil {
|
||||
return nil, errors.New("empty private key")
|
||||
}
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
|
||||
b.AddASN1BigInt(k.lambda)
|
||||
b.AddASN1BigInt(k.N)
|
||||
})
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
// Unmarshal 解码私钥
|
||||
func (k *PrivateKey) Unmarshal(b []byte) error {
|
||||
if k.lambda == nil || k.N == nil {
|
||||
k.lambda = new(big.Int)
|
||||
k.N = new(big.Int)
|
||||
}
|
||||
|
||||
input := cryptobyte.String(b)
|
||||
var inner cryptobyte.String
|
||||
if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
|
||||
!inner.ReadASN1Integer(k.lambda) ||
|
||||
!inner.ReadASN1Integer(k.N) {
|
||||
return errors.New("read ASN.1 private key failed")
|
||||
}
|
||||
|
||||
if k.lambdaInv == nil {
|
||||
k.lambdaInv = new(big.Int)
|
||||
}
|
||||
k.lambdaInv.ModInverse(k.lambda, k.N)
|
||||
|
||||
_ = k.Public()
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package paillier
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
)
|
||||
|
||||
// HomomorphicAdd set c = Enc(m1+m2) where c1 = Enc(m1) and c2 = Enc(m2)
|
||||
func (c *Cipher) HomomorphicAdd(c1 *Cipher, c2 *Cipher, pk *PublicKey) *Cipher {
|
||||
if c.D == nil {
|
||||
c.D = new(big.Int)
|
||||
}
|
||||
c.D.Mul(c1.D, c2.D)
|
||||
c.D.Mod(c.D, pk.N2)
|
||||
return c
|
||||
}
|
||||
|
||||
// HomomorphicAddInt set c = Enc(m1 + m) where c1 = Enc(m1) and m < N.
|
||||
//
|
||||
// Becareful, if the adversary knows c1, c, and m(or m1), then he can computes m1(or m).
|
||||
// So, using HomomorphicAddInt if you know what you're doing,
|
||||
// otherwise, you should use like this:
|
||||
// c2, err := pk.Encrypt(m, rnd)
|
||||
// c.HomomorphicAdd(c1, c2, pk)
|
||||
func (c *Cipher) HomomorphicAddInt(c1 *Cipher, m *big.Int, pk *PublicKey) *Cipher {
|
||||
d := new(big.Int)
|
||||
c.D = d.Mul(pk.N, m).Add(d, gmath.BigInt1).Mod(d, pk.N2).Mul(d, c1.D).Mod(d, pk.N2)
|
||||
return c
|
||||
}
|
||||
|
||||
// HomomorphicScalarMul if c1 = Enc(a), then HomomorphicScalarMul computes c = Enc(ka)
|
||||
// if ka < n^2.
|
||||
func (c *Cipher) HomomorphicScalarMul(a *Cipher, k *big.Int, pk *PublicKey) *Cipher {
|
||||
if c.D == nil {
|
||||
c.D = new(big.Int)
|
||||
}
|
||||
c.D.Exp(a.D, k, pk.N2)
|
||||
return c
|
||||
}
|
||||
|
||||
// Neg negates the plaintext mod n, i.e., if c = Enc(m), then c.Neg() = Enc(n-m).
|
||||
func (c *Cipher) Neg(pk *PublicKey) *Cipher {
|
||||
c.D.ModInverse(c.D, pk.N2)
|
||||
return c
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package paillier
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
)
|
||||
|
||||
func TestNeg(t *testing.T) {
|
||||
sk, err := GenerateKeyFromPassword(2048, grand.GetRandom(32), grand.GetRandom(32), 1024)
|
||||
assert.Nil(t, err)
|
||||
pk := sk.Public()
|
||||
|
||||
m, _ := rand.Int(grand.Reader, pk.N)
|
||||
mNeg := new(big.Int).Sub(pk.N, m) // n - m
|
||||
c, _ := Encrypt(m, pk, grand.Reader)
|
||||
|
||||
c.Neg(pk) // Enc(n-m) = Enc(m)^-1 mod n^2
|
||||
|
||||
mm, _ := Decrypt(c, sk)
|
||||
|
||||
assert.Zero(t, mm.Cmp(mNeg))
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
package paillier
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm2"
|
||||
)
|
||||
|
||||
func bigFromBase16(s string) *big.Int {
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return new(big.Int).SetBytes(b)
|
||||
}
|
||||
|
||||
var p = bigFromBase16("ff03b1a74827c746db83d2eaff00067622f545b62584321256e62b01509f1096" +
|
||||
"2f9c5c8fd0b7f5184a9ce8e81f439df47dda14563dd55a221799d2aa57ed2713" +
|
||||
"271678a5a0b8b40a84ad13d5b6e6599e6467c670109cf1f45ccfed8f75ea3b81" +
|
||||
"4548ab294626fe4d14ff764dd8b091f11a0943a2dd2b983b0df02f4c4d00b413")
|
||||
|
||||
var q = bigFromBase16("dacaabc1dc57faa9fd6a4274c4d588765a1d3311c22e57d8101431b07eb3ddcb" +
|
||||
"05d77d9a742ac2322fe6a063bd1e05acb13b0fe91c70115c2b1eee1155e07252" +
|
||||
"7011a5f849de7072a1ce8e6b71db525fbcda7a89aaed46d27aca5eaeaf35a262" +
|
||||
"70a4a833c5cda681ffd49baa0f610bad100cdf47cc86e5034e2a0b2179e04ec7")
|
||||
|
||||
var n = new(big.Int).Mul(p, q)
|
||||
var lambda = new(big.Int)
|
||||
|
||||
// lcm(lambda, new(big.Int).Sub(p, gmath.BigInt1), new(big.Int).Sub(q, gmath.BigInt1))
|
||||
|
||||
func TestPaillier(t *testing.T) {
|
||||
// pk, sk := GenerateKey(1024)
|
||||
|
||||
sk, err := GenerateKeyFromPassword(2048, grand.GetRandom(32), grand.GetRandom(32), 1024)
|
||||
assert.Nil(t, err)
|
||||
pk := sk.Public()
|
||||
|
||||
m1, _ := rand.Int(grand.Reader, pk.N)
|
||||
m2, _ := rand.Int(grand.Reader, pk.N)
|
||||
c1, _ := Encrypt(m1, pk, grand.Reader)
|
||||
c2, _ := Encrypt(m2, pk, grand.Reader)
|
||||
|
||||
c := new(Cipher).HomomorphicAdd(c1, c2, pk)
|
||||
m, _ := Decrypt(c, sk)
|
||||
|
||||
mm := new(big.Int).Add(m1, m2)
|
||||
mm.Mod(mm, pk.N)
|
||||
assert.Zero(t, m.Cmp(mm))
|
||||
}
|
||||
|
||||
func TestKeyMarshal(t *testing.T) {
|
||||
|
||||
sk, pk, err := GenerateKey(2048, grand.Reader)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, pk.Size(), uint(2048))
|
||||
|
||||
skBytes, err := sk.Marshal()
|
||||
assert.Nil(t, err)
|
||||
sk2 := new(PrivateKey)
|
||||
assert.Nil(t, sk2.Unmarshal(skBytes))
|
||||
assert.Zero(t, sk.p.Cmp(sk2.p)|sk.q.Cmp(sk2.q)|sk.lambda.Cmp(sk2.lambda)|sk.lambdaInv.Cmp(sk2.lambdaInv))
|
||||
|
||||
pkBytes, err := pk.Marshal()
|
||||
assert.Nil(t, err)
|
||||
pk2 := new(PublicKey)
|
||||
assert.Nil(t, pk2.Unmarshal(pkBytes))
|
||||
assert.Zero(t, pk.N.Cmp(pk2.N)|pk.N2.Cmp(pk2.N2))
|
||||
}
|
||||
|
||||
func TestPaillierScalarMul(t *testing.T) {
|
||||
sk, err := GenerateKeyFromPassword(2048, grand.GetRandom(32), grand.GetRandom(32), 1024)
|
||||
assert.Nil(t, err)
|
||||
pk := sk.Public()
|
||||
|
||||
limit := big.NewInt(1)
|
||||
limit.Lsh(limit, 256)
|
||||
ch := time.After(3 * time.Second)
|
||||
done := false
|
||||
for !done {
|
||||
select {
|
||||
case <-ch:
|
||||
done = true
|
||||
default:
|
||||
m, _ := rand.Int(grand.Reader, limit)
|
||||
k, _ := rand.Int(grand.Reader, limit)
|
||||
|
||||
c, _ := Encrypt(m, pk, grand.Reader)
|
||||
c.HomomorphicScalarMul(c, k, sk.Public())
|
||||
|
||||
m1, err := Decrypt(c, sk)
|
||||
assert.Nil(t, err)
|
||||
m2 := new(big.Int).Mul(m, k)
|
||||
assert.Zero(t, m1.Cmp(m2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkParallelPaillierEnc(b *testing.B) {
|
||||
_, pk, _ := GenerateKey(2048, grand.Reader)
|
||||
|
||||
m, _ := rand.Int(grand.Reader, pk.N)
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
Encrypt(m, pk, grand.Reader)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkPaillierEnc(b *testing.B) {
|
||||
_, pk, _ := GenerateKey(2048, grand.Reader)
|
||||
|
||||
m, _ := rand.Int(grand.Reader, pk.N)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Encrypt(m, pk, grand.Reader)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkPaillierDec(b *testing.B) {
|
||||
sk, pk, _ := GenerateKey(2048, grand.Reader)
|
||||
|
||||
m, _ := rand.Int(grand.Reader, pk.N)
|
||||
c, _ := Encrypt(m, pk, grand.Reader)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Decrypt(c, sk)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkPaillierHomomorphicScalarMul(b *testing.B) {
|
||||
sk, pk, _ := GenerateKey(2048, grand.Reader)
|
||||
|
||||
limit := big.NewInt(1)
|
||||
limit.Lsh(limit, 256)
|
||||
|
||||
m, _ := rand.Int(grand.Reader, limit)
|
||||
c, _ := Encrypt(m, pk, grand.Reader)
|
||||
|
||||
k, _ := rand.Int(grand.Reader, limit)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.HomomorphicScalarMul(c, k, sk.Public())
|
||||
}
|
||||
}
|
||||
func TestPaillierHomomorphicEncSpeed(t *testing.T) {
|
||||
_, pk, _ := GenerateKey(2048, grand.Reader)
|
||||
|
||||
m, _ := rand.Int(grand.Reader, pk.N)
|
||||
|
||||
times := 1000
|
||||
start := time.Now()
|
||||
for i := 0; i < times; i++ {
|
||||
Encrypt(m, pk, grand.Reader)
|
||||
}
|
||||
end := time.Now()
|
||||
elapsed := end.Sub(start)
|
||||
t.Logf("HomomorphicScalarMul: %.2f per second\n", float64(times)/elapsed.Seconds())
|
||||
}
|
||||
|
||||
func TestPaillierHomomorphicScalarMulSpeed(t *testing.T) {
|
||||
_, pk, _ := GenerateKey(2048, grand.Reader)
|
||||
|
||||
limit := big.NewInt(1)
|
||||
limit.Lsh(limit, 256)
|
||||
|
||||
m, _ := rand.Int(grand.Reader, limit)
|
||||
c, _ := Encrypt(m, pk, grand.Reader)
|
||||
|
||||
k, _ := rand.Int(grand.Reader, limit)
|
||||
|
||||
times := 1000
|
||||
start := time.Now()
|
||||
for i := 0; i < times; i++ {
|
||||
c.HomomorphicScalarMul(c, k, pk)
|
||||
}
|
||||
end := time.Now()
|
||||
elapsed := end.Sub(start)
|
||||
t.Logf("HomomorphicScalarMul: %.2f per second\n", float64(times)/elapsed.Seconds())
|
||||
}
|
||||
|
||||
func BenchmarkBlind1(b *testing.B) {
|
||||
_, pk, _ := GenerateKey(2048, grand.Reader)
|
||||
|
||||
limit := big.NewInt(1)
|
||||
limit.Lsh(limit, 256)
|
||||
|
||||
k, _ := rand.Int(grand.Reader, limit)
|
||||
nc, _ := pk.Encrypt(sm2.OrderN(), grand.Reader)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
(&Cipher{}).HomomorphicScalarMul(nc, k, pk)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkBlind2(b *testing.B) {
|
||||
_, pk, _ := GenerateKey(2048, grand.Reader)
|
||||
|
||||
limit := big.NewInt(1)
|
||||
limit.Lsh(limit, 256)
|
||||
|
||||
k, _ := rand.Int(grand.Reader, limit)
|
||||
kn := new(big.Int).Mul(k, sm2.OrderN())
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
kn.Mul(k, sm2.OrderN())
|
||||
pk.Encrypt(kn, grand.Reader)
|
||||
}
|
||||
}
|
||||
|
||||
// func BenchmarkGMPIntExp(b *testing.B) {
|
||||
// sk, _, _ := GenerateKey(2048, grand.Reader)
|
||||
// n := gmp.NewInt(1).SetBytes(sk.N.Bytes())
|
||||
// n2 := gmp.NewInt(1).Mul(n, n)
|
||||
|
||||
// r := gmp.NewInt(1).SetBytes(grand.GetRandom(128))
|
||||
// b.ResetTimer()
|
||||
// for i := 0; i < b.N; i++ {
|
||||
// r.Exp(r, n, n2)
|
||||
// }
|
||||
// }
|
||||
|
||||
func BenchmarkIntExp(b *testing.B) {
|
||||
sk, _, _ := GenerateKey(2048, grand.Reader)
|
||||
n := sk.N
|
||||
n2 := sk.N2
|
||||
|
||||
r := new(big.Int).SetBytes(grand.GetRandom(128))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
r.Exp(r, n, n2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateKeyFromPassword(t *testing.T) {
|
||||
b, _ := hex.DecodeString("12345678abcdef")
|
||||
sk, _ := GenerateKeyFromPassword(2048, []byte("1234567812345678"), b, 1024)
|
||||
assert.Equal(t, sk.N.Text(16), "86257d4f684edb672420a6e0d6a6e66b00a316080c0b025d96e9d22c57d6fc7166bcddc07dadc2f0dca7440c6f43a90fab494ea810304af2abc18d54bcdeb8803c8c245270d70b897f3bf2e43c3a5e9d777fb256f84cf5b4705cba19283952dd10aa2b15793a401195ee2a418b999bbf72e35bd94f48267597ab7cfb699b3bbab78a6201a9ee18a22d25e841a66c54d5ebf45c10491ea43cca5e9e6f487c7aedc24d15cda20e6f80a755477b6e2b1d1a9e669ba0773bb31e2fb76e550fdef1be4d02ec820aba5ebfbfd0fbb37bd1c748af1f4a0c17f5cfb41e4cb44a05587bcff2937415eb2e13398da514224def6c03f61a07319512362912caa08bded076dd")
|
||||
assert.Equal(t, sk.Size(), uint(2048))
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package x
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
)
|
||||
|
||||
func TestPaillier(t *testing.T) {
|
||||
// pk, sk := GenerateKey(1024)
|
||||
|
||||
sk, pk, err := GenerateKey(2048)
|
||||
assert.Nil(t, err)
|
||||
|
||||
m, _ := rand.Int(grand.Reader, pk.N)
|
||||
c, _ := Encrypt(m, pk, grand.Reader)
|
||||
m1, _ := Decrypt(c, sk)
|
||||
|
||||
assert.Zero(t, m.Cmp(m1))
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
package x
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"sync"
|
||||
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
"golang.org/x/crypto/cryptobyte/asn1"
|
||||
"xdx.jelly/xgcl/gmath"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
)
|
||||
|
||||
//
|
||||
// PublicKey ::= INTEGER
|
||||
//
|
||||
// PrivateKey ::= SEQUENCE{
|
||||
// lambda INTEGER,
|
||||
// N INTEGER
|
||||
// }
|
||||
//
|
||||
// Cipher ::= INTEGER
|
||||
|
||||
type PublicKey struct {
|
||||
N *big.Int
|
||||
N2 *big.Int
|
||||
|
||||
mu sync.Mutex // guard rn
|
||||
rn *big.Int
|
||||
}
|
||||
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
lambda *big.Int
|
||||
|
||||
// option
|
||||
lambdaInv *big.Int
|
||||
p, q *big.Int
|
||||
}
|
||||
|
||||
func (k *PrivateKey) Public() *PublicKey {
|
||||
if k.PublicKey.N2 == nil {
|
||||
k.PublicKey.N2 = new(big.Int).Mul(k.PublicKey.N, k.PublicKey.N)
|
||||
}
|
||||
if k.rn == nil {
|
||||
k.Precompute(grand.Reader)
|
||||
}
|
||||
return &k.PublicKey
|
||||
}
|
||||
|
||||
// Cipher the member variable D is for gcl's internal use.
|
||||
// You should never use it except you know what you're doing.
|
||||
type Cipher struct {
|
||||
D *big.Int
|
||||
}
|
||||
|
||||
func newPrivateKey(p *big.Int, q *big.Int, r *big.Int, s *big.Int) *PrivateKey {
|
||||
sk := &PrivateKey{
|
||||
PublicKey: PublicKey{
|
||||
N: new(big.Int).Mul(p, q),
|
||||
},
|
||||
lambda: new(big.Int),
|
||||
lambdaInv: new(big.Int),
|
||||
}
|
||||
N := sk.PublicKey.N
|
||||
N.Mul(N, r).Mul(N, s)
|
||||
pk := sk.Public()
|
||||
|
||||
// lambda = LCM(p-1, q-1) or just (p-1)*(q-1)
|
||||
// lcm(sk.lambda, new(big.Int).Sub(p, gmath.BigInt1), new(big.Int).Sub(q, gmath.BigInt1))
|
||||
sk.lambda.Mul(new(big.Int).Sub(p, gmath.BigInt1), new(big.Int).Sub(q, gmath.BigInt1))
|
||||
sk.lambda.Mul(sk.lambda, new(big.Int).Sub(r, gmath.BigInt1))
|
||||
sk.lambda.Mul(sk.lambda, new(big.Int).Sub(s, gmath.BigInt1))
|
||||
|
||||
sk.lambdaInv.ModInverse(sk.lambda, pk.N)
|
||||
return sk
|
||||
}
|
||||
|
||||
// return l = lcm(a,b)
|
||||
func lcm(l, a, b *big.Int) {
|
||||
d := new(big.Int).GCD(nil, nil, a, b)
|
||||
l.Mul(a, b)
|
||||
l.Div(l, d)
|
||||
}
|
||||
|
||||
// GenerateKey 生成同态密钥. bits 应为2048.
|
||||
// rnd_opt 可选, 忽略则使用grand.Reader.
|
||||
func GenerateKey(bits int, rnd_opt ...io.Reader) (*PrivateKey, *PublicKey, error) {
|
||||
var rnd io.Reader
|
||||
if len(rnd_opt) > 0 {
|
||||
rnd = rnd_opt[0]
|
||||
} else {
|
||||
rnd = grand.Reader
|
||||
}
|
||||
|
||||
priKey := &PrivateKey{}
|
||||
rsaKey1, err := rsa.GenerateKey(rnd, bits)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
rsaKey2, err := rsa.GenerateKey(rnd, bits)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// check rsaKey1 and rsaKey2 has no gcd > 1.
|
||||
priKey = newPrivateKey(rsaKey1.Primes[0], rsaKey1.Primes[1], rsaKey2.Primes[0], rsaKey2.Primes[1])
|
||||
|
||||
return priKey, &priKey.PublicKey, nil
|
||||
}
|
||||
|
||||
func (k *PrivateKey) Decrypt(c *Cipher) (*big.Int, error) {
|
||||
if c.D == nil || c.D.Cmp(k.N2) >= 0 {
|
||||
return nil, errors.New("invalid cipher")
|
||||
}
|
||||
if k.lambdaInv == nil {
|
||||
k.lambdaInv = new(big.Int).ModInverse(k.lambda, k.N)
|
||||
}
|
||||
pk := k.Public()
|
||||
d := c.D
|
||||
L := new(big.Int)
|
||||
L.Exp(d, k.lambda, pk.N2) // L = c^lambda mod n^2
|
||||
L.Sub(L, gmath.BigInt1)
|
||||
L.Div(L, pk.N) // L = (c^lambda - 1)/n
|
||||
L.Mul(L, k.lambdaInv)
|
||||
L.Mod(L, pk.N)
|
||||
return L, nil
|
||||
}
|
||||
func (k *PublicKey) Bits() int {
|
||||
return k.N.BitLen()
|
||||
}
|
||||
|
||||
// Precompute computes r^N mod N^2 for a random r.
|
||||
func (k *PublicKey) Precompute(rnd io.Reader) error {
|
||||
if k.rn != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
k.mu.Lock()
|
||||
defer k.mu.Unlock()
|
||||
|
||||
if k.N2 == nil {
|
||||
k.N2 = new(big.Int).Mul(k.N, k.N)
|
||||
}
|
||||
|
||||
if k.rn != nil {
|
||||
return nil
|
||||
}
|
||||
buf := make([]byte, k.N.BitLen()/2)
|
||||
_, err := rnd.Read(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf[0] |= 1 // at least one
|
||||
r := new(big.Int).SetBytes(buf)
|
||||
r.Exp(r, k.N, k.N2) // r = r^n mod n^2
|
||||
k.rn = r
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *PublicKey) Encrypt(m *big.Int, rnd io.Reader) (*Cipher, error) {
|
||||
if true {
|
||||
k.Precompute(grand.Reader)
|
||||
rn := new(big.Int).SetBytes(grand.GetRandom(12))
|
||||
rn.Exp(k.rn, rn, k.N2)
|
||||
|
||||
d := new(big.Int)
|
||||
d.Mul(k.N, m) // d = n * m
|
||||
d.Add(d, gmath.BigInt1) // d = nm + 1
|
||||
|
||||
d.Mul(d, rn) // c = (nm+1)*r^n mod n^2
|
||||
d.Mod(d, k.N2)
|
||||
return &Cipher{D: d}, nil
|
||||
} else {
|
||||
// r should select from (1, N)
|
||||
var r *big.Int
|
||||
var err error
|
||||
for {
|
||||
r, err = rand.Int(rnd, k.N)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// should we check gcd(r,n) == 1?
|
||||
if r.Sign() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d := new(big.Int)
|
||||
d.Mul(k.N, m) // d = n * m
|
||||
d.Add(d, gmath.BigInt1) // d = nm + 1
|
||||
|
||||
r.Exp(r, k.N, k.N2) // r = r^n mod n^2
|
||||
// r.SetUint64(1)
|
||||
d.Mul(d, r) // c = (nm+1)*r^n mod n^2
|
||||
d.Mod(d, k.N2)
|
||||
return &Cipher{D: d}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func Encrypt(m *big.Int, publicKey *PublicKey, rnd io.Reader) (*Cipher, error) {
|
||||
return publicKey.Encrypt(m, rnd)
|
||||
}
|
||||
|
||||
func Decrypt(c *Cipher, key *PrivateKey) (*big.Int, error) {
|
||||
return key.Decrypt(c)
|
||||
}
|
||||
|
||||
func (c *Cipher) Marshal() ([]byte, error) {
|
||||
if c.D == nil {
|
||||
return nil, errors.New("empty cipher")
|
||||
}
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BigInt(c.D)
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func (c *Cipher) Unmarshal(b []byte) error {
|
||||
if c.D == nil {
|
||||
c.D = new(big.Int)
|
||||
}
|
||||
input := cryptobyte.String(b)
|
||||
if !input.ReadASN1Integer(c.D) {
|
||||
return errors.New("parse ASN.1 cipher failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// round up n to the nearest power of 2.
|
||||
func roundup(n uint64) uint64 {
|
||||
n--
|
||||
n |= n >> 1
|
||||
n |= n >> 2
|
||||
n |= n >> 4
|
||||
n |= n >> 8
|
||||
n |= n >> 16
|
||||
n |= n >> 32
|
||||
return n + 1
|
||||
}
|
||||
|
||||
func (k *PublicKey) Size() uint {
|
||||
return uint(roundup(uint64(k.N.BitLen())))
|
||||
}
|
||||
|
||||
// Marshal 编码公钥, PublicKey ::= INTEGER
|
||||
func (k *PublicKey) Marshal() ([]byte, error) {
|
||||
if k.N == nil {
|
||||
return nil, errors.New("empty public key")
|
||||
}
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BigInt(k.N)
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func (k *PublicKey) Unmarshal(b []byte) error {
|
||||
if k.N == nil || k.N2 == nil {
|
||||
k.N = new(big.Int)
|
||||
k.N2 = new(big.Int)
|
||||
}
|
||||
|
||||
input := cryptobyte.String(b)
|
||||
if !input.ReadASN1Integer(k.N) {
|
||||
return errors.New("parse ASN.1 public key failed")
|
||||
}
|
||||
|
||||
k.N2.Mul(k.N, k.N)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalExt 编码公钥,包括预计算数据, PublicKey ::= INTEGER
|
||||
func (k *PublicKey) MarshalExt() ([]byte, error) {
|
||||
if k.N == nil {
|
||||
return nil, errors.New("empty public key")
|
||||
}
|
||||
k.Precompute(grand.Reader)
|
||||
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
|
||||
b.AddASN1BigInt(k.N)
|
||||
b.AddASN1BigInt(k.rn)
|
||||
})
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func (k *PublicKey) UnmarshalExt(b []byte) error {
|
||||
if k.N == nil || k.N2 == nil {
|
||||
k.N = new(big.Int)
|
||||
k.N2 = new(big.Int)
|
||||
}
|
||||
if k.rn == nil {
|
||||
k.rn = new(big.Int)
|
||||
}
|
||||
|
||||
input := cryptobyte.String(b)
|
||||
var inner cryptobyte.String
|
||||
if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
|
||||
!inner.ReadASN1Integer(k.N) ||
|
||||
!inner.ReadASN1Integer(k.rn) {
|
||||
return errors.New("read ASN.1 private key failed")
|
||||
}
|
||||
|
||||
k.N2.Mul(k.N, k.N)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal 编码私钥
|
||||
func (k *PrivateKey) Marshal() ([]byte, error) {
|
||||
if k.lambda == nil {
|
||||
return nil, errors.New("empty private key")
|
||||
}
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
|
||||
b.AddASN1BigInt(k.lambda)
|
||||
b.AddASN1BigInt(k.N)
|
||||
})
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
// Unmarshal 解码私钥
|
||||
func (k *PrivateKey) Unmarshal(b []byte) error {
|
||||
if k.lambda == nil || k.N == nil {
|
||||
k.lambda = new(big.Int)
|
||||
k.N = new(big.Int)
|
||||
}
|
||||
|
||||
input := cryptobyte.String(b)
|
||||
var inner cryptobyte.String
|
||||
if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
|
||||
!inner.ReadASN1Integer(k.lambda) ||
|
||||
!inner.ReadASN1Integer(k.N) {
|
||||
return errors.New("read ASN.1 private key failed")
|
||||
}
|
||||
|
||||
if k.lambdaInv == nil {
|
||||
k.lambdaInv = new(big.Int)
|
||||
}
|
||||
k.lambdaInv.ModInverse(k.lambda, k.N)
|
||||
|
||||
_ = k.Public()
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user