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 }