status-go/vendor/github.com/libp2p/go-libp2p-secio/al.go

123 lines
2.5 KiB
Go
Raw Normal View History

package secio
import (
"errors"
"fmt"
"strings"
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/sha1"
"crypto/sha512"
"hash"
ci "github.com/libp2p/go-libp2p-crypto"
sha256 "github.com/minio/sha256-simd"
bfish "golang.org/x/crypto/blowfish"
)
// SupportedExchanges is the list of supported ECDH curves
var SupportedExchanges = DefaultSupportedExchanges
const DefaultSupportedExchanges = "P-256,P-384,P-521"
// SupportedCiphers is the list of supported Ciphers
var SupportedCiphers = DefaultSupportedCiphers
const DefaultSupportedCiphers = "AES-256,AES-128,Blowfish"
// SupportedHashes is the list of supported Hashes
var SupportedHashes = DefaultSupportedHashes
const DefaultSupportedHashes = "SHA256,SHA512"
// HMAC carries a hash and its size
type HMAC struct {
hash.Hash
size int
}
// encParams represent encryption parameters
type encParams struct {
// keys
permanentPubKey ci.PubKey
ephemeralPubKey []byte
keys ci.StretchedKeys
// selections
curveT string
cipherT string
hashT string
// cipher + mac
cipher cipher.Stream
mac HMAC
}
func (e *encParams) makeMacAndCipher() error {
m, err := newMac(e.hashT, e.keys.MacKey)
if err != nil {
return err
}
bc, err := newBlockCipher(e.cipherT, e.keys.CipherKey)
if err != nil {
return err
}
e.cipher = cipher.NewCTR(bc, e.keys.IV)
e.mac = m
return nil
}
func newMac(hashType string, key []byte) (HMAC, error) {
switch hashType {
case "SHA1":
return HMAC{hmac.New(sha1.New, key), sha1.Size}, nil
case "SHA512":
return HMAC{hmac.New(sha512.New, key), sha512.Size}, nil
case "SHA256":
return HMAC{hmac.New(sha256.New, key), sha256.Size}, nil
default:
return HMAC{}, fmt.Errorf("Unrecognized hash type: %s", hashType)
}
}
func newBlockCipher(cipherT string, key []byte) (cipher.Block, error) {
switch cipherT {
case "AES-128", "AES-256":
return aes.NewCipher(key)
case "Blowfish":
return bfish.NewCipher(key)
default:
return nil, fmt.Errorf("Unrecognized cipher type: %s", cipherT)
}
}
// Determines which algorithm to use. Note: f(a, b) = f(b, a)
func selectBest(order int, p1, p2 string) (string, error) {
var f, s []string
switch {
case order < 0:
f = strings.Split(p2, ",")
s = strings.Split(p1, ",")
case order > 0:
f = strings.Split(p1, ",")
s = strings.Split(p2, ",")
default: // Exact same preferences.
p := strings.Split(p1, ",")
return p[0], nil
}
for _, fc := range f {
for _, sc := range s {
if fc == sc {
return fc, nil
}
}
}
return "", errors.New("No algorithms in common!")
}