github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/p2p/crypto/secio/al.go (about)

     1  package secio
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"crypto/aes"
     9  	"crypto/cipher"
    10  	"crypto/hmac"
    11  	"crypto/sha1"
    12  	"crypto/sha256"
    13  	"crypto/sha512"
    14  	"hash"
    15  
    16  	bfish "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/crypto/blowfish"
    17  	ci "github.com/ipfs/go-ipfs/p2p/crypto"
    18  )
    19  
    20  // List of supported ECDH curves
    21  var SupportedExchanges = "P-256,P-384,P-521"
    22  
    23  // List of supported Ciphers
    24  var SupportedCiphers = "AES-256,AES-128,Blowfish"
    25  
    26  // List of supported Hashes
    27  var SupportedHashes = "SHA256,SHA512"
    28  
    29  type HMAC struct {
    30  	hash.Hash
    31  	size int
    32  }
    33  
    34  // encParams represent encryption parameters
    35  type encParams struct {
    36  	// keys
    37  	permanentPubKey ci.PubKey
    38  	ephemeralPubKey []byte
    39  	keys            ci.StretchedKeys
    40  
    41  	// selections
    42  	curveT  string
    43  	cipherT string
    44  	hashT   string
    45  
    46  	// cipher + mac
    47  	cipher cipher.Stream
    48  	mac    HMAC
    49  }
    50  
    51  func (e *encParams) makeMacAndCipher() error {
    52  	m, err := newMac(e.hashT, e.keys.MacKey)
    53  	if err != nil {
    54  		return err
    55  	}
    56  
    57  	bc, err := newBlockCipher(e.cipherT, e.keys.CipherKey)
    58  	if err != nil {
    59  		return err
    60  	}
    61  
    62  	e.cipher = cipher.NewCTR(bc, e.keys.IV)
    63  	e.mac = m
    64  	return nil
    65  }
    66  
    67  func newMac(hashType string, key []byte) (HMAC, error) {
    68  	switch hashType {
    69  	case "SHA1":
    70  		return HMAC{hmac.New(sha1.New, key), sha1.Size}, nil
    71  	case "SHA512":
    72  		return HMAC{hmac.New(sha512.New, key), sha512.Size}, nil
    73  	case "SHA256":
    74  		return HMAC{hmac.New(sha256.New, key), sha256.Size}, nil
    75  	default:
    76  		return HMAC{}, fmt.Errorf("Unrecognized hash type: %s", hashType)
    77  	}
    78  }
    79  
    80  func newBlockCipher(cipherT string, key []byte) (cipher.Block, error) {
    81  	switch cipherT {
    82  	case "AES-128", "AES-256":
    83  		return aes.NewCipher(key)
    84  	case "Blowfish":
    85  		return bfish.NewCipher(key)
    86  	default:
    87  		return nil, fmt.Errorf("Unrecognized cipher type: %s", cipherT)
    88  	}
    89  }
    90  
    91  // Determines which algorithm to use.  Note:  f(a, b) = f(b, a)
    92  func selectBest(order int, p1, p2 string) (string, error) {
    93  	var f, s []string
    94  	switch {
    95  	case order < 0:
    96  		f = strings.Split(p2, ",")
    97  		s = strings.Split(p1, ",")
    98  	case order > 0:
    99  		f = strings.Split(p1, ",")
   100  		s = strings.Split(p2, ",")
   101  	default: // Exact same preferences.
   102  		p := strings.Split(p1, ",")
   103  		return p[0], nil
   104  	}
   105  
   106  	for _, fc := range f {
   107  		for _, sc := range s {
   108  			if fc == sc {
   109  				return fc, nil
   110  			}
   111  		}
   112  	}
   113  
   114  	return "", errors.New("No algorithms in common!")
   115  }