github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/core/access_contoller/crypto/paillier/util.go (about)

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