github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/p2p/crypto/key.go (about) 1 // package crypto implements various cryptographic utilities used by ipfs. 2 // This includes a Public and Private key interface and an RSA key implementation 3 // that satisfies it. 4 package crypto 5 6 import ( 7 "bytes" 8 "encoding/base64" 9 "errors" 10 "fmt" 11 "io" 12 13 "crypto/elliptic" 14 "crypto/hmac" 15 "crypto/rand" 16 "crypto/rsa" 17 "crypto/sha1" 18 "crypto/sha256" 19 "crypto/sha512" 20 "hash" 21 22 proto "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/gogo/protobuf/proto" 23 24 pb "github.com/ipfs/go-ipfs/p2p/crypto/pb" 25 u "github.com/ipfs/go-ipfs/util" 26 ) 27 28 var log = u.Logger("crypto") 29 30 var ErrBadKeyType = errors.New("invalid or unsupported key type") 31 32 const ( 33 RSA = iota 34 ) 35 36 // Key represents a crypto key that can be compared to another key 37 type Key interface { 38 // Bytes returns a serialized, storeable representation of this key 39 Bytes() ([]byte, error) 40 41 // Hash returns the hash of this key 42 Hash() ([]byte, error) 43 44 // Equals checks whether two PubKeys are the same 45 Equals(Key) bool 46 } 47 48 // PrivKey represents a private key that can be used to generate a public key, 49 // sign data, and decrypt data that was encrypted with a public key 50 type PrivKey interface { 51 Key 52 53 // Cryptographically sign the given bytes 54 Sign([]byte) ([]byte, error) 55 56 // Return a public key paired with this private key 57 GetPublic() PubKey 58 59 // Generate a secret string of bytes 60 GenSecret() []byte 61 62 Decrypt(b []byte) ([]byte, error) 63 } 64 65 type PubKey interface { 66 Key 67 68 // Verify that 'sig' is the signed hash of 'data' 69 Verify(data []byte, sig []byte) (bool, error) 70 71 // Encrypt data in a way that can be decrypted by a paired private key 72 Encrypt(data []byte) ([]byte, error) 73 } 74 75 // Given a public key, generates the shared key. 76 type GenSharedKey func([]byte) ([]byte, error) 77 78 func GenerateKeyPair(typ, bits int) (PrivKey, PubKey, error) { 79 return GenerateKeyPairWithReader(typ, bits, rand.Reader) 80 } 81 82 // Generates a keypair of the given type and bitsize 83 func GenerateKeyPairWithReader(typ, bits int, src io.Reader) (PrivKey, PubKey, error) { 84 switch typ { 85 case RSA: 86 priv, err := rsa.GenerateKey(src, bits) 87 if err != nil { 88 return nil, nil, err 89 } 90 pk := &priv.PublicKey 91 return &RsaPrivateKey{sk: priv}, &RsaPublicKey{pk}, nil 92 default: 93 return nil, nil, ErrBadKeyType 94 } 95 } 96 97 // Generates an ephemeral public key and returns a function that will compute 98 // the shared secret key. Used in the identify module. 99 // 100 // Focuses only on ECDH now, but can be made more general in the future. 101 func GenerateEKeyPair(curveName string) ([]byte, GenSharedKey, error) { 102 var curve elliptic.Curve 103 104 switch curveName { 105 case "P-256": 106 curve = elliptic.P256() 107 case "P-384": 108 curve = elliptic.P384() 109 case "P-521": 110 curve = elliptic.P521() 111 } 112 113 priv, x, y, err := elliptic.GenerateKey(curve, rand.Reader) 114 if err != nil { 115 return nil, nil, err 116 } 117 118 pubKey := elliptic.Marshal(curve, x, y) 119 // log.Debug("GenerateEKeyPair %d", len(pubKey)) 120 121 done := func(theirPub []byte) ([]byte, error) { 122 // Verify and unpack node's public key. 123 x, y := elliptic.Unmarshal(curve, theirPub) 124 if x == nil { 125 return nil, fmt.Errorf("Malformed public key: %d %v", len(theirPub), theirPub) 126 } 127 128 if !curve.IsOnCurve(x, y) { 129 return nil, errors.New("Invalid public key.") 130 } 131 132 // Generate shared secret. 133 secret, _ := curve.ScalarMult(x, y, priv) 134 135 return secret.Bytes(), nil 136 } 137 138 return pubKey, done, nil 139 } 140 141 type StretchedKeys struct { 142 IV []byte 143 MacKey []byte 144 CipherKey []byte 145 } 146 147 // Generates a set of keys for each party by stretching the shared key. 148 // (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey) 149 func KeyStretcher(cipherType string, hashType string, secret []byte) (StretchedKeys, StretchedKeys) { 150 var cipherKeySize int 151 var ivSize int 152 switch cipherType { 153 case "AES-128": 154 ivSize = 16 155 cipherKeySize = 16 156 case "AES-256": 157 ivSize = 16 158 cipherKeySize = 32 159 case "Blowfish": 160 ivSize = 8 161 // Note: 24 arbitrarily selected, needs more thought 162 cipherKeySize = 32 163 } 164 165 hmacKeySize := 20 166 167 seed := []byte("key expansion") 168 169 result := make([]byte, 2*(ivSize+cipherKeySize+hmacKeySize)) 170 171 var h func() hash.Hash 172 173 switch hashType { 174 case "SHA1": 175 h = sha1.New 176 case "SHA256": 177 h = sha256.New 178 case "SHA512": 179 h = sha512.New 180 default: 181 panic("Unrecognized hash function, programmer error?") 182 } 183 184 m := hmac.New(h, secret) 185 m.Write(seed) 186 187 a := m.Sum(nil) 188 189 j := 0 190 for j < len(result) { 191 m.Reset() 192 m.Write(a) 193 m.Write(seed) 194 b := m.Sum(nil) 195 196 todo := len(b) 197 198 if j+todo > len(result) { 199 todo = len(result) - j 200 } 201 202 copy(result[j:j+todo], b) 203 204 j += todo 205 206 m.Reset() 207 m.Write(a) 208 a = m.Sum(nil) 209 } 210 211 half := len(result) / 2 212 r1 := result[:half] 213 r2 := result[half:] 214 215 var k1 StretchedKeys 216 var k2 StretchedKeys 217 218 k1.IV = r1[0:ivSize] 219 k1.CipherKey = r1[ivSize : ivSize+cipherKeySize] 220 k1.MacKey = r1[ivSize+cipherKeySize:] 221 222 k2.IV = r2[0:ivSize] 223 k2.CipherKey = r2[ivSize : ivSize+cipherKeySize] 224 k2.MacKey = r2[ivSize+cipherKeySize:] 225 226 return k1, k2 227 } 228 229 // UnmarshalPublicKey converts a protobuf serialized public key into its 230 // representative object 231 func UnmarshalPublicKey(data []byte) (PubKey, error) { 232 pmes := new(pb.PublicKey) 233 err := proto.Unmarshal(data, pmes) 234 if err != nil { 235 return nil, err 236 } 237 238 switch pmes.GetType() { 239 case pb.KeyType_RSA: 240 return UnmarshalRsaPublicKey(pmes.GetData()) 241 default: 242 return nil, ErrBadKeyType 243 } 244 } 245 246 // MarshalPublicKey converts a public key object into a protobuf serialized 247 // public key 248 func MarshalPublicKey(k PubKey) ([]byte, error) { 249 b, err := MarshalRsaPublicKey(k.(*RsaPublicKey)) 250 if err != nil { 251 return nil, err 252 } 253 pmes := new(pb.PublicKey) 254 typ := pb.KeyType_RSA // for now only type. 255 pmes.Type = &typ 256 pmes.Data = b 257 return proto.Marshal(pmes) 258 } 259 260 // UnmarshalPrivateKey converts a protobuf serialized private key into its 261 // representative object 262 func UnmarshalPrivateKey(data []byte) (PrivKey, error) { 263 pmes := new(pb.PrivateKey) 264 err := proto.Unmarshal(data, pmes) 265 if err != nil { 266 return nil, err 267 } 268 269 switch pmes.GetType() { 270 case pb.KeyType_RSA: 271 return UnmarshalRsaPrivateKey(pmes.GetData()) 272 default: 273 return nil, ErrBadKeyType 274 } 275 } 276 277 // MarshalPrivateKey converts a key object into its protobuf serialized form. 278 func MarshalPrivateKey(k PrivKey) ([]byte, error) { 279 b := MarshalRsaPrivateKey(k.(*RsaPrivateKey)) 280 pmes := new(pb.PrivateKey) 281 typ := pb.KeyType_RSA // for now only type. 282 pmes.Type = &typ 283 pmes.Data = b 284 return proto.Marshal(pmes) 285 } 286 287 // ConfigDecodeKey decodes from b64 (for config file), and unmarshals. 288 func ConfigDecodeKey(b string) ([]byte, error) { 289 return base64.StdEncoding.DecodeString(b) 290 } 291 292 // ConfigEncodeKey encodes to b64 (for config file), and marshals. 293 func ConfigEncodeKey(b []byte) string { 294 return base64.StdEncoding.EncodeToString(b) 295 } 296 297 // KeyEqual checks whether two 298 func KeyEqual(k1, k2 Key) bool { 299 if k1 == k2 { 300 return true 301 } 302 303 b1, err1 := k1.Bytes() 304 b2, err2 := k2.Bytes() 305 return bytes.Equal(b1, b2) && err1 == err2 306 } 307 308 // KeyHash hashes a key. 309 func KeyHash(k Key) ([]byte, error) { 310 kb, err := k.Bytes() 311 if err != nil { 312 return nil, err 313 } 314 return u.Hash(kb), nil 315 }