gitee.com/lh-her-team/common@v1.5.1/helper/libp2pcrypto/key.go (about) 1 // Package crypto implements various cryptographic utilities used by libp2p. 2 // This includes a Public and Private key interface and key implementations 3 // for supported key algorithms. 4 package libp2pcrypto 5 6 // nolint: gosec 7 import ( 8 "crypto/elliptic" 9 "crypto/hmac" 10 "crypto/rand" 11 "crypto/sha1" 12 "crypto/sha512" 13 "crypto/subtle" 14 "encoding/base64" 15 "errors" 16 "fmt" 17 "hash" 18 "io" 19 20 "gitee.com/lh-her-team/common/helper/libp2pcrypto/pb" 21 22 "github.com/gogo/protobuf/proto" 23 sha256 "github.com/minio/sha256-simd" 24 ) 25 26 const ( 27 // RSA is an enum for the supported RSA key type 28 RSA = iota 29 // Ed25519 is an enum for the supported Ed25519 key type 30 Ed25519 31 // Secp256k1 is an enum for the supported Secp256k1 key type 32 Secp256k1 33 // ECDSA is an enum for the supported ECDSA key type 34 ECDSA 35 // SM2 is an enum for the supported SM2 key type 36 SM2 37 ) 38 39 var ( 40 // ErrBadKeyType is returned when a key is not supported 41 ErrBadKeyType = errors.New("invalid or unsupported key type") 42 // KeyTypes is a list of supported keys 43 KeyTypes = []int{ 44 RSA, 45 Ed25519, 46 Secp256k1, 47 ECDSA, 48 SM2, 49 } 50 ) 51 52 // PubKeyUnmarshaller is a func that creates a PubKey from a given slice of bytes 53 type PubKeyUnmarshaller func(data []byte) (PubKey, error) 54 55 // PrivKeyUnmarshaller is a func that creates a PrivKey from a given slice of bytes 56 type PrivKeyUnmarshaller func(data []byte) (PrivKey, error) 57 58 // PubKeyUnmarshallers is a map of unmarshallers by key type 59 var PubKeyUnmarshallers = map[pb.KeyType]PubKeyUnmarshaller{ 60 pb.KeyType_RSA: UnmarshalRsaPublicKey, 61 pb.KeyType_Ed25519: UnmarshalEd25519PublicKey, 62 pb.KeyType_Secp256k1: UnmarshalSecp256k1PublicKey, 63 pb.KeyType_ECDSA: UnmarshalECDSAPublicKey, 64 pb.KeyType_SM2: UnmarshalSM2PublicKey, 65 } 66 67 // PrivKeyUnmarshallers is a map of unmarshallers by key type 68 var PrivKeyUnmarshallers = map[pb.KeyType]PrivKeyUnmarshaller{ 69 pb.KeyType_RSA: UnmarshalRsaPrivateKey, 70 pb.KeyType_Ed25519: UnmarshalEd25519PrivateKey, 71 pb.KeyType_Secp256k1: UnmarshalSecp256k1PrivateKey, 72 pb.KeyType_ECDSA: UnmarshalECDSAPrivateKey, 73 pb.KeyType_SM2: UnmarshalSM2PrivateKey, 74 } 75 76 // Key represents a crypto key that can be compared to another key 77 type Key interface { 78 // Bytes returns a serialized, storeable representation of this key 79 // DEPRECATED in favor of Marshal / Unmarshal 80 Bytes() ([]byte, error) 81 // Equals checks whether two PubKeys are the same 82 Equals(Key) bool 83 // Raw returns the raw bytes of the key (not wrapped in the 84 // libp2p-crypto protobuf). 85 // 86 // This function is the inverse of {Priv,Pub}KeyUnmarshaler. 87 Raw() ([]byte, error) 88 // Type returns the protobof key type. 89 Type() pb.KeyType 90 } 91 92 // PrivKey represents a private key that can be used to generate a public key and sign data 93 type PrivKey interface { 94 Key 95 // Cryptographically sign the given bytes 96 Sign([]byte) ([]byte, error) 97 // Return a public key paired with this private key 98 GetPublic() PubKey 99 } 100 101 // PubKey is a public key that can be used to verifiy data signed with the corresponding private key 102 type PubKey interface { 103 Key 104 // Verify that 'sig' is the signed hash of 'data' 105 Verify(data []byte, sig []byte) (bool, error) 106 } 107 108 // GenSharedKey generates the shared key from a given private key 109 type GenSharedKey func([]byte) ([]byte, error) 110 111 // GenerateKeyPair generates a private and public key 112 func GenerateKeyPair(typ, bits int) (PrivKey, PubKey, error) { 113 return GenerateKeyPairWithReader(typ, bits, rand.Reader) 114 } 115 116 // GenerateKeyPairWithReader returns a keypair of the given type and bitsize 117 func GenerateKeyPairWithReader(typ, bits int, src io.Reader) (PrivKey, PubKey, error) { 118 switch typ { 119 case RSA: 120 return GenerateRSAKeyPair(bits, src) 121 case Ed25519: 122 return GenerateEd25519Key(src) 123 case Secp256k1: 124 return GenerateSecp256k1Key(src) 125 case ECDSA: 126 return GenerateECDSAKeyPair(src) 127 default: 128 return nil, nil, ErrBadKeyType 129 } 130 } 131 132 // GenerateEKeyPair returns an ephemeral public key and returns a function that will compute 133 // the shared secret key. Used in the identify module. 134 // 135 // Focuses only on ECDH now, but can be made more general in the future. 136 func GenerateEKeyPair(curveName string) ([]byte, GenSharedKey, error) { 137 var curve elliptic.Curve 138 switch curveName { 139 case "P-256": 140 curve = elliptic.P256() 141 case "P-384": 142 curve = elliptic.P384() 143 case "P-521": 144 curve = elliptic.P521() 145 default: 146 return nil, nil, fmt.Errorf("unknown curve name") 147 } 148 priv, x, y, err := elliptic.GenerateKey(curve, rand.Reader) 149 if err != nil { 150 return nil, nil, err 151 } 152 pubKey := elliptic.Marshal(curve, x, y) 153 done := func(theirPub []byte) ([]byte, error) { 154 // Verify and unpack node's public key. 155 x, y := elliptic.Unmarshal(curve, theirPub) 156 if x == nil { 157 return nil, fmt.Errorf("malformed public key: %d %v", len(theirPub), theirPub) 158 } 159 if !curve.IsOnCurve(x, y) { 160 return nil, errors.New("invalid public key") 161 } 162 // Generate shared secret. 163 secret, _ := curve.ScalarMult(x, y, priv) 164 return secret.Bytes(), nil 165 } 166 return pubKey, done, nil 167 } 168 169 // StretchedKeys ... 170 type StretchedKeys struct { 171 IV []byte 172 MacKey []byte 173 CipherKey []byte 174 } 175 176 // PENDING DEPRECATION: KeyStretcher() will be deprecated with secio; for new 177 // code, please use PBKDF2 (golang.org/x/crypto/pbkdf2) instead. 178 // KeyStretcher returns a set of keys for each party by stretching the shared key. 179 // (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey). 180 // This function accepts the following cipher types: 181 // - AES-128 182 // - AES-256 183 // The function will panic upon receiving an unknown cipherType 184 func KeyStretcher(cipherType string, hashType string, secret []byte) (StretchedKeys, StretchedKeys) { 185 var cipherKeySize int 186 var ivSize int 187 switch cipherType { 188 case "AES-128": 189 ivSize = 16 190 cipherKeySize = 16 191 case "AES-256": 192 ivSize = 16 193 cipherKeySize = 32 194 default: 195 panic("Unrecognized cipher, programmer error?") 196 } 197 hmacKeySize := 20 198 seed := []byte("key expansion") 199 result := make([]byte, 2*(ivSize+cipherKeySize+hmacKeySize)) 200 var h func() hash.Hash 201 switch hashType { 202 case "SHA1": 203 h = sha1.New 204 case "SHA256": 205 h = sha256.New 206 case "SHA512": 207 h = sha512.New 208 default: 209 panic("Unrecognized hash function, programmer error?") 210 } 211 m := hmac.New(h, secret) 212 // note: guaranteed to never return an error 213 m.Write(seed) 214 a := m.Sum(nil) 215 j := 0 216 for j < len(result) { 217 m.Reset() 218 // note: guaranteed to never return an error. 219 m.Write(a) 220 m.Write(seed) 221 b := m.Sum(nil) 222 todo := len(b) 223 if j+todo > len(result) { 224 todo = len(result) - j 225 } 226 copy(result[j:j+todo], b) 227 j += todo 228 m.Reset() 229 // note: guaranteed to never return an error. 230 m.Write(a) 231 a = m.Sum(nil) 232 } 233 half := len(result) / 2 234 r1 := result[:half] 235 r2 := result[half:] 236 var k1 StretchedKeys 237 var k2 StretchedKeys 238 k1.IV = r1[0:ivSize] 239 k1.CipherKey = r1[ivSize : ivSize+cipherKeySize] 240 k1.MacKey = r1[ivSize+cipherKeySize:] 241 k2.IV = r2[0:ivSize] 242 k2.CipherKey = r2[ivSize : ivSize+cipherKeySize] 243 k2.MacKey = r2[ivSize+cipherKeySize:] 244 return k1, k2 245 } 246 247 // UnmarshalPublicKey converts a protobuf serialized public key into its 248 // representative object 249 func UnmarshalPublicKey(data []byte) (PubKey, error) { 250 pmes := new(pb.PublicKey) 251 err := proto.Unmarshal(data, pmes) 252 if err != nil { 253 return nil, err 254 } 255 return PublicKeyFromProto(pmes) 256 } 257 258 // PublicKeyFromProto converts an unserialized protobuf PublicKey message 259 // into its representative object. 260 func PublicKeyFromProto(pmes *pb.PublicKey) (PubKey, error) { 261 um, ok := PubKeyUnmarshallers[pmes.GetType()] 262 if !ok { 263 return nil, ErrBadKeyType 264 } 265 data := pmes.GetData() 266 pk, err := um(data) 267 if err != nil { 268 return nil, err 269 } 270 switch tpk := pk.(type) { 271 case *RsaPublicKey: 272 tpk.cached, _ = pmes.Marshal() 273 } 274 return pk, nil 275 } 276 277 // MarshalPublicKey converts a public key object into a protobuf serialized 278 // public key 279 func MarshalPublicKey(k PubKey) ([]byte, error) { 280 pbmes, err := PublicKeyToProto(k) 281 if err != nil { 282 return nil, err 283 } 284 return proto.Marshal(pbmes) 285 } 286 287 // PublicKeyToProto converts a public key object into an unserialized 288 // protobuf PublicKey message. 289 func PublicKeyToProto(k PubKey) (*pb.PublicKey, error) { 290 pbmes := new(pb.PublicKey) 291 pbmes.Type = k.Type() 292 data, err := k.Raw() 293 if err != nil { 294 return nil, err 295 } 296 pbmes.Data = data 297 return pbmes, nil 298 } 299 300 // UnmarshalPrivateKey converts a protobuf serialized private key into its 301 // representative object 302 func UnmarshalPrivateKey(data []byte) (PrivKey, error) { 303 pmes := new(pb.PrivateKey) 304 err := proto.Unmarshal(data, pmes) 305 if err != nil { 306 return nil, err 307 } 308 um, ok := PrivKeyUnmarshallers[pmes.GetType()] 309 if !ok { 310 return nil, ErrBadKeyType 311 } 312 return um(pmes.GetData()) 313 } 314 315 // MarshalPrivateKey converts a key object into its protobuf serialized form. 316 func MarshalPrivateKey(k PrivKey) ([]byte, error) { 317 pbmes := new(pb.PrivateKey) 318 pbmes.Type = k.Type() 319 data, err := k.Raw() 320 if err != nil { 321 return nil, err 322 } 323 pbmes.Data = data 324 return proto.Marshal(pbmes) 325 } 326 327 // ConfigDecodeKey decodes from b64 (for config file) to a byte array that can be unmarshalled. 328 func ConfigDecodeKey(b string) ([]byte, error) { 329 return base64.StdEncoding.DecodeString(b) 330 } 331 332 // ConfigEncodeKey encodes a marshalled key to b64 (for config file). 333 func ConfigEncodeKey(b []byte) string { 334 return base64.StdEncoding.EncodeToString(b) 335 } 336 337 // KeyEqual checks whether two Keys are equivalent (have identical byte representations). 338 func KeyEqual(k1, k2 Key) bool { 339 if k1 == k2 { 340 return true 341 } 342 343 return k1.Equals(k2) 344 } 345 346 func basicEquals(k1, k2 Key) bool { 347 if k1.Type() != k2.Type() { 348 return false 349 } 350 a, err := k1.Raw() 351 if err != nil { 352 return false 353 } 354 b, err := k2.Raw() 355 if err != nil { 356 return false 357 } 358 return subtle.ConstantTimeCompare(a, b) == 1 359 }