gitee.com/lh-her-team/common@v1.5.1/crypto/paillier/util.go (about)

     1  package paillier
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/asn1"
     6  	"encoding/pem"
     7  	"errors"
     8  	"io/ioutil"
     9  	"math/big"
    10  )
    11  
    12  const (
    13  	defaultChecksumSize = 5
    14  )
    15  
    16  func AdjustPlaintextDomain(pk *PubKey, plaintext *big.Int) (*big.Int, error) {
    17  	plaintext = new(big.Int).Mod(plaintext, pk.N)
    18  	return plaintext, nil
    19  }
    20  
    21  func AdjustDecryptedDomain(pk *PubKey, plaintext *big.Int) (*big.Int, error) {
    22  	limitUp := new(big.Int).Div(pk.N, big.NewInt(2))
    23  	if new(big.Int).Mod(pk.N, big.NewInt(2)).Cmp(one) == 0 {
    24  		limitUp = new(big.Int).Add(limitUp, one)
    25  	}
    26  	plaintext = new(big.Int).Mod(plaintext, pk.N)
    27  	if plaintext.Cmp(limitUp) == 1 {
    28  		plaintext = new(big.Int).Sub(plaintext, pk.N)
    29  	}
    30  	return plaintext, nil
    31  }
    32  
    33  // validatePrvKey is used to validate the private key
    34  func validatePrvKey(key *PrvKey) error {
    35  	if key == nil || key.p == nil || key.q == nil {
    36  		return ErrInvalidPrivateKey
    37  	}
    38  	if err := validatePubKey(key.PubKey); err != nil {
    39  		return ErrInvalidPrivateKey
    40  	}
    41  	return nil
    42  }
    43  
    44  // validatePubKey is used to validate the public key
    45  func validatePubKey(key *PubKey) error {
    46  	if key == nil || key.G == nil || key.N == nil || key.NSquared == nil {
    47  		return ErrInvalidPublicKey
    48  	}
    49  	return nil
    50  }
    51  
    52  // validateCiphertext is used to validate Ciphertext
    53  func validateCiphertext(cts ...*Ciphertext) error {
    54  	for _, ct := range cts {
    55  		if ct == nil || ct.Ct == nil || ct.Checksum == nil {
    56  			return ErrInvalidCiphertext
    57  		}
    58  	}
    59  	return nil
    60  }
    61  
    62  // validatePlaintext is used to validate the paillier Ciphertext of type big.Int
    63  func validatePlaintext(paillierTexts ...*big.Int) error {
    64  	for _, paillierText := range paillierTexts {
    65  		if paillierText == nil {
    66  			return ErrInvalidPlaintext
    67  		}
    68  	}
    69  	return nil
    70  }
    71  
    72  // public key io
    73  func GetPublicKeyHex(pk *PubKey) string {
    74  	n := pk.N.Text(16)
    75  	return n
    76  }
    77  
    78  func GetPublicKeyFromHex(content string) (*PubKey, error) {
    79  	n, isOK := new(big.Int).SetString(content, 16)
    80  	if !isOK {
    81  		//return nil, errors.New("invalid string for Paillier public key: " + content)
    82  		return nil, ErrInvalidPublicKey
    83  	}
    84  	return &PubKey{
    85  		N:        n,
    86  		NSquared: new(big.Int).Mul(n, n),
    87  		G:        new(big.Int).Add(n, one),
    88  	}, nil
    89  }
    90  
    91  // nolint: gosec
    92  func WritePublicKeyToFile(pk *PubKey, file string) error {
    93  	return ioutil.WriteFile(file, []byte(GetPublicKeyHex(pk)), 0644)
    94  }
    95  
    96  func ReadPublicKeyFromFile(file string) (*PubKey, error) {
    97  	content, err := ioutil.ReadFile(file)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	return GetPublicKeyFromHex(string(content))
   102  }
   103  
   104  // private key io
   105  func GetPrivateKeyHex(sk *PrvKey) string {
   106  	// TO DER
   107  	pkDER, err := asn1.Marshal(
   108  		struct {
   109  			P      *big.Int
   110  			Q      *big.Int
   111  			PubStr string
   112  		}{
   113  			sk.p,
   114  			sk.q,
   115  			GetPublicKeyHex(sk.PubKey),
   116  		})
   117  	if err != nil {
   118  		return ""
   119  	}
   120  	// PEM encode
   121  	block := &pem.Block{
   122  		Type:  "PAILLIER PRIVATE KEY",
   123  		Bytes: pkDER,
   124  	}
   125  	buf := new(bytes.Buffer)
   126  	if err = pem.Encode(buf, block); err != nil {
   127  		return ""
   128  	}
   129  	return buf.String()
   130  }
   131  
   132  func GetPrivateKeyFromHex(content string) (*PrvKey, error) {
   133  	temp := struct {
   134  		P      *big.Int
   135  		Q      *big.Int
   136  		PubStr string
   137  	}{}
   138  	// PEM decode
   139  	block, rest := pem.Decode([]byte(content))
   140  	if len(rest) != 0 {
   141  		return nil, ErrInvalidPrivateKey
   142  	}
   143  	// DER to struct
   144  	_, err := asn1.Unmarshal(block.Bytes, &temp)
   145  	if err != nil {
   146  		return nil, ErrInvalidPrivateKey
   147  	}
   148  	p := temp.P
   149  	q := temp.Q
   150  	n := new(big.Int).Mul(p, q)
   151  	pp := new(big.Int).Mul(p, p)
   152  	qq := new(big.Int).Mul(q, q)
   153  	return &PrvKey{
   154  		PubKey: &PubKey{
   155  			N:        n,
   156  			NSquared: new(big.Int).Mul(n, n),
   157  			G:        new(big.Int).Add(n, one),
   158  		},
   159  		p:         p,
   160  		pp:        pp,
   161  		pminusone: new(big.Int).Sub(p, one),
   162  		q:         q,
   163  		qq:        qq,
   164  		qminusone: new(big.Int).Sub(q, one),
   165  		pinvq:     new(big.Int).ModInverse(p, q),
   166  		hp:        h(p, pp, n),
   167  		hq:        h(q, qq, n),
   168  		n:         n,
   169  	}, nil
   170  }
   171  
   172  func WritePrivateKeyToFile(sk *PrvKey, file string) error {
   173  	return WriteEncryptedPrivateKeyToFile(sk, file, "")
   174  }
   175  
   176  // nolint: gosec
   177  func WriteEncryptedPrivateKeyToFile(sk *PrvKey, file, password string) error {
   178  	if password == "" {
   179  		return ioutil.WriteFile(file, []byte(GetPrivateKeyHex(sk)), 0644)
   180  	}
   181  	// TODO: implement secret key encryption here
   182  	return ioutil.WriteFile(file, []byte(GetPrivateKeyHex(sk)), 0644)
   183  }
   184  
   185  func ReadPrivateKeyFromFile(file string) (*PrvKey, error) {
   186  	return ReadEncryptedPrivateKeyFromFile(file, "")
   187  }
   188  
   189  func ReadEncryptedPrivateKeyFromFile(file, password string) (*PrvKey, error) {
   190  	content, err := ioutil.ReadFile(file)
   191  	if err != nil {
   192  		return nil, err
   193  	}
   194  	if password == "" {
   195  		return GetPrivateKeyFromHex(string(content))
   196  	}
   197  	// TODO: implement secret key decryption here
   198  	return GetPrivateKeyFromHex(string(content))
   199  }
   200  
   201  // ciphertext io
   202  func GetCiphertextHex(cipher string) (string, error) {
   203  	c, isOk := new(big.Int).SetString(cipher, 10)
   204  	if !isOk {
   205  		return "", ErrInvalidCiphertext
   206  	}
   207  	return c.Text(16), nil
   208  }
   209  
   210  func GetCiphertextFromHex(content string) (string, error) {
   211  	c, isOK := new(big.Int).SetString(content, 16)
   212  	if !isOK {
   213  		return "", errors.New("invalid string for paillier ciphertext: " + content)
   214  	}
   215  	return c.Text(10), nil
   216  }
   217  
   218  // nolint: gosec
   219  func WriteCiphertextToFile(cipher string, file string) error {
   220  	content, err := GetCiphertextHex(cipher)
   221  	if err != nil {
   222  		return err
   223  	}
   224  	return ioutil.WriteFile(file, []byte(content), 0644)
   225  }
   226  
   227  func ReadCiphertextFromFile(file string) (string, error) {
   228  	content, err := ioutil.ReadFile(file)
   229  	if err != nil {
   230  		return "", err
   231  	}
   232  	return GetCiphertextFromHex(string(content))
   233  }