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  }