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 }