123 lines
2.5 KiB
Go
123 lines
2.5 KiB
Go
|
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!")
|
||
|
}
|