diff options
Diffstat (limited to 'Godeps')
-rw-r--r-- | Godeps/Godeps.json | 6 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/obscuren/ecies/.gitignore | 24 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/obscuren/ecies/LICENSE | 28 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/obscuren/ecies/README | 94 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/obscuren/ecies/asn1.go | 556 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/obscuren/ecies/ecies.go | 326 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/obscuren/ecies/ecies_test.go | 489 | ||||
-rw-r--r-- | Godeps/_workspace/src/github.com/obscuren/ecies/params.go | 187 |
8 files changed, 1 insertions, 1709 deletions
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 831140690..9fa7373c8 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,6 +1,6 @@ { "ImportPath": "github.com/ethereum/go-ethereum", - "GoVersion": "go1.4", + "GoVersion": "go1.4.1", "Packages": [ "./..." ], @@ -58,10 +58,6 @@ "Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1" }, { - "ImportPath": "github.com/obscuren/ecies", - "Rev": "d899334bba7bf4a157cab19d8ad836dcb1de0c34" - }, - { "ImportPath": "github.com/obscuren/otto", "Rev": "cf13cc4228c5e5ce0fe27a7aea90bc10091c4f19" }, diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/.gitignore b/Godeps/_workspace/src/github.com/obscuren/ecies/.gitignore deleted file mode 100644 index 802b6744a..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/ecies/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe - -*~ diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/LICENSE b/Godeps/_workspace/src/github.com/obscuren/ecies/LICENSE deleted file mode 100644 index e1ed19a27..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/ecies/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2013 Kyle Isom <kyle@tyrfingr.is> -Copyright (c) 2012 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/README b/Godeps/_workspace/src/github.com/obscuren/ecies/README deleted file mode 100644 index 2650c7b9f..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/ecies/README +++ /dev/null @@ -1,94 +0,0 @@ -# NOTE - -This implementation is direct fork of Kylom's implementation. I claim no authorship over this code apart from some minor modifications. -Please be aware this code **has not yet been reviewed**. - -ecies implements the Elliptic Curve Integrated Encryption Scheme. - -The package is designed to be compliant with the appropriate NIST -standards, and therefore doesn't support the full SEC 1 algorithm set. - - -STATUS: - -ecies should be ready for use. The ASN.1 support is only complete so -far as to supported the listed algorithms before. - - -CAVEATS - -1. CMAC support is currently not present. - - -SUPPORTED ALGORITHMS - - SYMMETRIC CIPHERS HASH FUNCTIONS - AES128 SHA-1 - AES192 SHA-224 - AES256 SHA-256 - SHA-384 - ELLIPTIC CURVE SHA-512 - P256 - P384 KEY DERIVATION FUNCTION - P521 NIST SP 800-65a Concatenation KDF - -Curve P224 isn't supported because it does not provide a minimum security -level of AES128 with HMAC-SHA1. According to NIST SP 800-57, the security -level of P224 is 112 bits of security. Symmetric ciphers use CTR-mode; -message tags are computed using HMAC-<HASH> function. - - -CURVE SELECTION - -According to NIST SP 800-57, the following curves should be selected: - - +----------------+-------+ - | SYMMETRIC SIZE | CURVE | - +----------------+-------+ - | 128-bit | P256 | - +----------------+-------+ - | 192-bit | P384 | - +----------------+-------+ - | 256-bit | P521 | - +----------------+-------+ - - -TODO - -1. Look at serialising the parameters with the SEC 1 ASN.1 module. -2. Validate ASN.1 formats with SEC 1. - - -TEST VECTORS - -The only test vectors I've found so far date from 1993, predating AES -and including only 163-bit curves. Therefore, there are no published -test vectors to compare to. - - -LICENSE - -ecies is released under the same license as the Go source code. See the -LICENSE file for details. - - -REFERENCES - -* SEC (Standard for Efficient Cryptography) 1, version 2.0: Elliptic - Curve Cryptography; Certicom, May 2009. - http://www.secg.org/sec1-v2.pdf -* GEC (Guidelines for Efficient Cryptography) 2, version 0.3: Test - Vectors for SEC 1; Certicom, September 1999. - http://read.pudn.com/downloads168/doc/772358/TestVectorsforSEC%201-gec2.pdf -* NIST SP 800-56a: Recommendation for Pair-Wise Key Establishment Schemes - Using Discrete Logarithm Cryptography. National Institute of Standards - and Technology, May 2007. - http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf -* Suite B Implementer’s Guide to NIST SP 800-56A. National Security - Agency, July 28, 2009. - http://www.nsa.gov/ia/_files/SuiteB_Implementer_G-113808.pdf -* NIST SP 800-57: Recommendation for Key Management – Part 1: General - (Revision 3). National Institute of Standards and Technology, July - 2012. - http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf - diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/asn1.go b/Godeps/_workspace/src/github.com/obscuren/ecies/asn1.go deleted file mode 100644 index 3ef194ea0..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/ecies/asn1.go +++ /dev/null @@ -1,556 +0,0 @@ -package ecies - -import ( - "bytes" - "crypto" - "crypto/elliptic" - "crypto/sha1" - "crypto/sha256" - "crypto/sha512" - "encoding/asn1" - "encoding/pem" - "fmt" - "hash" - "math/big" -) - -var ( - secgScheme = []int{1, 3, 132, 1} - shaScheme = []int{2, 16, 840, 1, 101, 3, 4, 2} - ansiX962Scheme = []int{1, 2, 840, 10045} - x963Scheme = []int{1, 2, 840, 63, 0} -) - -var ErrInvalidPrivateKey = fmt.Errorf("ecies: invalid private key") - -func doScheme(base, v []int) asn1.ObjectIdentifier { - var oidInts asn1.ObjectIdentifier - oidInts = append(oidInts, base...) - return append(oidInts, v...) -} - -// curve OID code taken from crypto/x509, including -// - oidNameCurve* -// - namedCurveFromOID -// - oidFromNamedCurve -// RFC 5480, 2.1.1.1. Named Curve -// -// secp224r1 OBJECT IDENTIFIER ::= { -// iso(1) identified-organization(3) certicom(132) curve(0) 33 } -// -// secp256r1 OBJECT IDENTIFIER ::= { -// iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) -// prime(1) 7 } -// -// secp384r1 OBJECT IDENTIFIER ::= { -// iso(1) identified-organization(3) certicom(132) curve(0) 34 } -// -// secp521r1 OBJECT IDENTIFIER ::= { -// iso(1) identified-organization(3) certicom(132) curve(0) 35 } -// -// NB: secp256r1 is equivalent to prime256v1 -type secgNamedCurve asn1.ObjectIdentifier - -var ( - secgNamedCurveP224 = secgNamedCurve{1, 3, 132, 0, 33} - secgNamedCurveP256 = secgNamedCurve{1, 2, 840, 10045, 3, 1, 7} - secgNamedCurveP384 = secgNamedCurve{1, 3, 132, 0, 34} - secgNamedCurveP521 = secgNamedCurve{1, 3, 132, 0, 35} - rawCurveP224 = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 3} - rawCurveP256 = []byte{6, 8, 4, 2, 1, 3, 4, 7, 2, 2, 0, 6, 6, 1, 3, 1, 7} - rawCurveP384 = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 4} - rawCurveP521 = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 5} -) - -func rawCurve(curve elliptic.Curve) []byte { - switch curve { - case elliptic.P224(): - return rawCurveP224 - case elliptic.P256(): - return rawCurveP256 - case elliptic.P384(): - return rawCurveP384 - case elliptic.P521(): - return rawCurveP521 - default: - return nil - } -} - -func (curve secgNamedCurve) Equal(curve2 secgNamedCurve) bool { - if len(curve) != len(curve2) { - return false - } - for i, _ := range curve { - if curve[i] != curve2[i] { - return false - } - } - return true -} - -func namedCurveFromOID(curve secgNamedCurve) elliptic.Curve { - switch { - case curve.Equal(secgNamedCurveP224): - return elliptic.P224() - case curve.Equal(secgNamedCurveP256): - return elliptic.P256() - case curve.Equal(secgNamedCurveP384): - return elliptic.P384() - case curve.Equal(secgNamedCurveP521): - return elliptic.P521() - } - return nil -} - -func oidFromNamedCurve(curve elliptic.Curve) (secgNamedCurve, bool) { - switch curve { - case elliptic.P224(): - return secgNamedCurveP224, true - case elliptic.P256(): - return secgNamedCurveP256, true - case elliptic.P384(): - return secgNamedCurveP384, true - case elliptic.P521(): - return secgNamedCurveP521, true - } - - return nil, false -} - -// asnAlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC -// 5280, section 4.1.1.2. -type asnAlgorithmIdentifier struct { - Algorithm asn1.ObjectIdentifier - Parameters asn1.RawValue `asn1:"optional"` -} - -func (a asnAlgorithmIdentifier) Cmp(b asnAlgorithmIdentifier) bool { - if len(a.Algorithm) != len(b.Algorithm) { - return false - } - for i, _ := range a.Algorithm { - if a.Algorithm[i] != b.Algorithm[i] { - return false - } - } - return true -} - -type asnHashFunction asnAlgorithmIdentifier - -var ( - oidSHA1 = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26} - oidSHA224 = doScheme(shaScheme, []int{4}) - oidSHA256 = doScheme(shaScheme, []int{1}) - oidSHA384 = doScheme(shaScheme, []int{2}) - oidSHA512 = doScheme(shaScheme, []int{3}) -) - -func hashFromOID(oid asn1.ObjectIdentifier) func() hash.Hash { - switch { - case oid.Equal(oidSHA1): - return sha1.New - case oid.Equal(oidSHA224): - return sha256.New224 - case oid.Equal(oidSHA256): - return sha256.New - case oid.Equal(oidSHA384): - return sha512.New384 - case oid.Equal(oidSHA512): - return sha512.New - } - return nil -} - -func oidFromHash(hash crypto.Hash) (asn1.ObjectIdentifier, bool) { - switch hash { - case crypto.SHA1: - return oidSHA1, true - case crypto.SHA224: - return oidSHA224, true - case crypto.SHA256: - return oidSHA256, true - case crypto.SHA384: - return oidSHA384, true - case crypto.SHA512: - return oidSHA512, true - default: - return nil, false - } -} - -var ( - asnAlgoSHA1 = asnHashFunction{ - Algorithm: oidSHA1, - } - asnAlgoSHA224 = asnHashFunction{ - Algorithm: oidSHA224, - } - asnAlgoSHA256 = asnHashFunction{ - Algorithm: oidSHA256, - } - asnAlgoSHA384 = asnHashFunction{ - Algorithm: oidSHA384, - } - asnAlgoSHA512 = asnHashFunction{ - Algorithm: oidSHA512, - } -) - -// type ASNasnSubjectPublicKeyInfo struct { -// -// } -// - -type asnSubjectPublicKeyInfo struct { - Algorithm asn1.ObjectIdentifier - PublicKey asn1.BitString - Supplements ecpksSupplements `asn1:"optional"` -} - -type asnECPKAlgorithms struct { - Type asn1.ObjectIdentifier -} - -var idPublicKeyType = doScheme(ansiX962Scheme, []int{2}) -var idEcPublicKey = doScheme(idPublicKeyType, []int{1}) -var idEcPublicKeySupplemented = doScheme(idPublicKeyType, []int{0}) - -func curveToRaw(curve elliptic.Curve) (rv asn1.RawValue, ok bool) { - switch curve { - case elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521(): - raw := rawCurve(curve) - return asn1.RawValue{ - Tag: 30, - Bytes: raw[2:], - FullBytes: raw, - }, true - default: - return rv, false - } -} - -func asnECPublicKeyType(curve elliptic.Curve) (algo asnAlgorithmIdentifier, ok bool) { - raw, ok := curveToRaw(curve) - if !ok { - return - } else { - return asnAlgorithmIdentifier{Algorithm: idEcPublicKey, - Parameters: raw}, true - } -} - -type asnECPrivKeyVer int - -var asnECPrivKeyVer1 asnECPrivKeyVer = 1 - -type asnPrivateKey struct { - Version asnECPrivKeyVer - Private []byte - Curve secgNamedCurve `asn1:"optional"` - Public asn1.BitString -} - -var asnECDH = doScheme(secgScheme, []int{12}) - -type asnECDHAlgorithm asnAlgorithmIdentifier - -var ( - dhSinglePass_stdDH_sha1kdf = asnECDHAlgorithm{ - Algorithm: doScheme(x963Scheme, []int{2}), - } - dhSinglePass_stdDH_sha256kdf = asnECDHAlgorithm{ - Algorithm: doScheme(secgScheme, []int{11, 1}), - } - dhSinglePass_stdDH_sha384kdf = asnECDHAlgorithm{ - Algorithm: doScheme(secgScheme, []int{11, 2}), - } - dhSinglePass_stdDH_sha224kdf = asnECDHAlgorithm{ - Algorithm: doScheme(secgScheme, []int{11, 0}), - } - dhSinglePass_stdDH_sha512kdf = asnECDHAlgorithm{ - Algorithm: doScheme(secgScheme, []int{11, 3}), - } -) - -func (a asnECDHAlgorithm) Cmp(b asnECDHAlgorithm) bool { - if len(a.Algorithm) != len(b.Algorithm) { - return false - } - for i, _ := range a.Algorithm { - if a.Algorithm[i] != b.Algorithm[i] { - return false - } - } - return true -} - -// asnNISTConcatenation is the only supported KDF at this time. -type asnKeyDerivationFunction asnAlgorithmIdentifier - -var asnNISTConcatenationKDF = asnKeyDerivationFunction{ - Algorithm: doScheme(secgScheme, []int{17, 1}), -} - -func (a asnKeyDerivationFunction) Cmp(b asnKeyDerivationFunction) bool { - if len(a.Algorithm) != len(b.Algorithm) { - return false - } - for i, _ := range a.Algorithm { - if a.Algorithm[i] != b.Algorithm[i] { - return false - } - } - return true -} - -var eciesRecommendedParameters = doScheme(secgScheme, []int{7}) -var eciesSpecifiedParameters = doScheme(secgScheme, []int{8}) - -type asnECIESParameters struct { - KDF asnKeyDerivationFunction `asn1:"optional"` - Sym asnSymmetricEncryption `asn1:"optional"` - MAC asnMessageAuthenticationCode `asn1:"optional"` -} - -type asnSymmetricEncryption asnAlgorithmIdentifier - -var ( - aes128CTRinECIES = asnSymmetricEncryption{ - Algorithm: doScheme(secgScheme, []int{21, 0}), - } - aes192CTRinECIES = asnSymmetricEncryption{ - Algorithm: doScheme(secgScheme, []int{21, 1}), - } - aes256CTRinECIES = asnSymmetricEncryption{ - Algorithm: doScheme(secgScheme, []int{21, 2}), - } -) - -func (a asnSymmetricEncryption) Cmp(b asnSymmetricEncryption) bool { - if len(a.Algorithm) != len(b.Algorithm) { - return false - } - for i, _ := range a.Algorithm { - if a.Algorithm[i] != b.Algorithm[i] { - return false - } - } - return true -} - -type asnMessageAuthenticationCode asnAlgorithmIdentifier - -var ( - hmacFull = asnMessageAuthenticationCode{ - Algorithm: doScheme(secgScheme, []int{22}), - } -) - -func (a asnMessageAuthenticationCode) Cmp(b asnMessageAuthenticationCode) bool { - if len(a.Algorithm) != len(b.Algorithm) { - return false - } - for i, _ := range a.Algorithm { - if a.Algorithm[i] != b.Algorithm[i] { - return false - } - } - return true -} - -type ecpksSupplements struct { - ECDomain secgNamedCurve - ECCAlgorithms eccAlgorithmSet -} - -type eccAlgorithmSet struct { - ECDH asnECDHAlgorithm `asn1:"optional"` - ECIES asnECIESParameters `asn1:"optional"` -} - -func marshalSubjectPublicKeyInfo(pub *PublicKey) (subj asnSubjectPublicKeyInfo, err error) { - subj.Algorithm = idEcPublicKeySupplemented - curve, ok := oidFromNamedCurve(pub.Curve) - if !ok { - err = ErrInvalidPublicKey - return - } - subj.Supplements.ECDomain = curve - if pub.Params != nil { - subj.Supplements.ECCAlgorithms.ECDH = paramsToASNECDH(pub.Params) - subj.Supplements.ECCAlgorithms.ECIES = paramsToASNECIES(pub.Params) - } - pubkey := elliptic.Marshal(pub.Curve, pub.X, pub.Y) - subj.PublicKey = asn1.BitString{ - BitLength: len(pubkey) * 8, - Bytes: pubkey, - } - return -} - -// Encode a public key to DER format. -func MarshalPublic(pub *PublicKey) ([]byte, error) { - subj, err := marshalSubjectPublicKeyInfo(pub) - if err != nil { - return nil, err - } - return asn1.Marshal(subj) -} - -// Decode a DER-encoded public key. -func UnmarshalPublic(in []byte) (pub *PublicKey, err error) { - var subj asnSubjectPublicKeyInfo - - if _, err = asn1.Unmarshal(in, &subj); err != nil { - return - } - if !subj.Algorithm.Equal(idEcPublicKeySupplemented) { - err = ErrInvalidPublicKey - return - } - pub = new(PublicKey) - pub.Curve = namedCurveFromOID(subj.Supplements.ECDomain) - x, y := elliptic.Unmarshal(pub.Curve, subj.PublicKey.Bytes) - if x == nil { - err = ErrInvalidPublicKey - return - } - pub.X = x - pub.Y = y - pub.Params = new(ECIESParams) - asnECIEStoParams(subj.Supplements.ECCAlgorithms.ECIES, pub.Params) - asnECDHtoParams(subj.Supplements.ECCAlgorithms.ECDH, pub.Params) - if pub.Params == nil { - if pub.Params = ParamsFromCurve(pub.Curve); pub.Params == nil { - err = ErrInvalidPublicKey - } - } - return -} - -func marshalPrivateKey(prv *PrivateKey) (ecprv asnPrivateKey, err error) { - ecprv.Version = asnECPrivKeyVer1 - ecprv.Private = prv.D.Bytes() - - var ok bool - ecprv.Curve, ok = oidFromNamedCurve(prv.PublicKey.Curve) - if !ok { - err = ErrInvalidPrivateKey - return - } - - var pub []byte - if pub, err = MarshalPublic(&prv.PublicKey); err != nil { - return - } else { - ecprv.Public = asn1.BitString{ - BitLength: len(pub) * 8, - Bytes: pub, - } - } - return -} - -// Encode a private key to DER format. -func MarshalPrivate(prv *PrivateKey) ([]byte, error) { - ecprv, err := marshalPrivateKey(prv) - if err != nil { - return nil, err - } - return asn1.Marshal(ecprv) -} - -// Decode a private key from a DER-encoded format. -func UnmarshalPrivate(in []byte) (prv *PrivateKey, err error) { - var ecprv asnPrivateKey - - if _, err = asn1.Unmarshal(in, &ecprv); err != nil { - return - } else if ecprv.Version != asnECPrivKeyVer1 { - err = ErrInvalidPrivateKey - return - } - - privateCurve := namedCurveFromOID(ecprv.Curve) - if privateCurve == nil { - err = ErrInvalidPrivateKey - return - } - - prv = new(PrivateKey) - prv.D = new(big.Int).SetBytes(ecprv.Private) - - if pub, err := UnmarshalPublic(ecprv.Public.Bytes); err != nil { - return nil, err - } else { - prv.PublicKey = *pub - } - - return -} - -// Export a public key to PEM format. -func ExportPublicPEM(pub *PublicKey) (out []byte, err error) { - der, err := MarshalPublic(pub) - if err != nil { - return - } - - var block pem.Block - block.Type = "ELLIPTIC CURVE PUBLIC KEY" - block.Bytes = der - - buf := new(bytes.Buffer) - err = pem.Encode(buf, &block) - if err != nil { - return - } else { - out = buf.Bytes() - } - return -} - -// Export a private key to PEM format. -func ExportPrivatePEM(prv *PrivateKey) (out []byte, err error) { - der, err := MarshalPrivate(prv) - if err != nil { - return - } - - var block pem.Block - block.Type = "ELLIPTIC CURVE PRIVATE KEY" - block.Bytes = der - - buf := new(bytes.Buffer) - err = pem.Encode(buf, &block) - if err != nil { - return - } else { - out = buf.Bytes() - } - return -} - -// Import a PEM-encoded public key. -func ImportPublicPEM(in []byte) (pub *PublicKey, err error) { - p, _ := pem.Decode(in) - if p == nil || p.Type != "ELLIPTIC CURVE PUBLIC KEY" { - return nil, ErrInvalidPublicKey - } - - pub, err = UnmarshalPublic(p.Bytes) - return -} - -// Import a PEM-encoded private key. -func ImportPrivatePEM(in []byte) (prv *PrivateKey, err error) { - p, _ := pem.Decode(in) - if p == nil || p.Type != "ELLIPTIC CURVE PRIVATE KEY" { - return nil, ErrInvalidPrivateKey - } - - prv, err = UnmarshalPrivate(p.Bytes) - return -} diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/ecies.go b/Godeps/_workspace/src/github.com/obscuren/ecies/ecies.go deleted file mode 100644 index 0e2403d47..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/ecies/ecies.go +++ /dev/null @@ -1,326 +0,0 @@ -package ecies - -import ( - "crypto/cipher" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/hmac" - "crypto/subtle" - "fmt" - "hash" - "io" - "math/big" -) - -var ( - ErrImport = fmt.Errorf("ecies: failed to import key") - ErrInvalidCurve = fmt.Errorf("ecies: invalid elliptic curve") - ErrInvalidParams = fmt.Errorf("ecies: invalid ECIES parameters") - ErrInvalidPublicKey = fmt.Errorf("ecies: invalid public key") - ErrSharedKeyTooBig = fmt.Errorf("ecies: shared key is too big") -) - -// PublicKey is a representation of an elliptic curve public key. -type PublicKey struct { - X *big.Int - Y *big.Int - elliptic.Curve - Params *ECIESParams -} - -// Export an ECIES public key as an ECDSA public key. -func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey { - return &ecdsa.PublicKey{pub.Curve, pub.X, pub.Y} -} - -// Import an ECDSA public key as an ECIES public key. -func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey { - return &PublicKey{ - X: pub.X, - Y: pub.Y, - Curve: pub.Curve, - Params: ParamsFromCurve(pub.Curve), - } -} - -// PrivateKey is a representation of an elliptic curve private key. -type PrivateKey struct { - PublicKey - D *big.Int -} - -// Export an ECIES private key as an ECDSA private key. -func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey { - pub := &prv.PublicKey - pubECDSA := pub.ExportECDSA() - return &ecdsa.PrivateKey{*pubECDSA, prv.D} -} - -// Import an ECDSA private key as an ECIES private key. -func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey { - pub := ImportECDSAPublic(&prv.PublicKey) - return &PrivateKey{*pub, prv.D} -} - -// Generate an elliptic curve public / private keypair. If params is nil, -// the recommended default paramters for the key will be chosen. -func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) { - pb, x, y, err := elliptic.GenerateKey(curve, rand) - if err != nil { - return - } - prv = new(PrivateKey) - prv.PublicKey.X = x - prv.PublicKey.Y = y - prv.PublicKey.Curve = curve - prv.D = new(big.Int).SetBytes(pb) - if params == nil { - params = ParamsFromCurve(curve) - } - prv.PublicKey.Params = params - return -} - -// MaxSharedKeyLength returns the maximum length of the shared key the -// public key can produce. -func MaxSharedKeyLength(pub *PublicKey) int { - return (pub.Curve.Params().BitSize + 7) / 8 -} - -// ECDH key agreement method used to establish secret keys for encryption. -func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) { - if prv.PublicKey.Curve != pub.Curve { - err = ErrInvalidCurve - return - } - x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, prv.D.Bytes()) - if x == nil || (x.BitLen()+7)/8 < (skLen+macLen) { - err = ErrSharedKeyTooBig - return - } - sk = x.Bytes()[:skLen+macLen] - return -} - -var ( - ErrKeyDataTooLong = fmt.Errorf("ecies: can't supply requested key data") - ErrSharedTooLong = fmt.Errorf("ecies: shared secret is too long") - ErrInvalidMessage = fmt.Errorf("ecies: invalid message") -) - -var ( - big2To32 = new(big.Int).Exp(big.NewInt(2), big.NewInt(32), nil) - big2To32M1 = new(big.Int).Sub(big2To32, big.NewInt(1)) -) - -func incCounter(ctr []byte) { - if ctr[3]++; ctr[3] != 0 { - return - } else if ctr[2]++; ctr[2] != 0 { - return - } else if ctr[1]++; ctr[1] != 0 { - return - } else if ctr[0]++; ctr[0] != 0 { - return - } - return -} - -// NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1). -func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) { - if s1 == nil { - s1 = make([]byte, 0) - } - - reps := ((kdLen + 7) * 8) / (hash.BlockSize() * 8) - if big.NewInt(int64(reps)).Cmp(big2To32M1) > 0 { - fmt.Println(big2To32M1) - return nil, ErrKeyDataTooLong - } - - counter := []byte{0, 0, 0, 1} - k = make([]byte, 0) - - for i := 0; i <= reps; i++ { - hash.Write(counter) - hash.Write(z) - hash.Write(s1) - k = append(k, hash.Sum(nil)...) - hash.Reset() - incCounter(counter) - } - - k = k[:kdLen] - return -} - -// messageTag computes the MAC of a message (called the tag) as per -// SEC 1, 3.5. -func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte { - if shared == nil { - shared = make([]byte, 0) - } - mac := hmac.New(hash, km) - mac.Write(msg) - tag := mac.Sum(nil) - return tag -} - -// Generate an initialisation vector for CTR mode. -func generateIV(params *ECIESParams, rand io.Reader) (iv []byte, err error) { - iv = make([]byte, params.BlockSize) - _, err = io.ReadFull(rand, iv) - return -} - -// symEncrypt carries out CTR encryption using the block cipher specified in the -// parameters. -func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte, err error) { - c, err := params.Cipher(key) - if err != nil { - return - } - - iv, err := generateIV(params, rand) - if err != nil { - return - } - ctr := cipher.NewCTR(c, iv) - - ct = make([]byte, len(m)+params.BlockSize) - copy(ct, iv) - ctr.XORKeyStream(ct[params.BlockSize:], m) - return -} - -// symDecrypt carries out CTR decryption using the block cipher specified in -// the parameters -func symDecrypt(rand io.Reader, params *ECIESParams, key, ct []byte) (m []byte, err error) { - c, err := params.Cipher(key) - if err != nil { - return - } - - ctr := cipher.NewCTR(c, ct[:params.BlockSize]) - - m = make([]byte, len(ct)-params.BlockSize) - ctr.XORKeyStream(m, ct[params.BlockSize:]) - return -} - -// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. If -// the shared information parameters aren't being used, they should be -// nil. -func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) { - params := pub.Params - if params == nil { - if params = ParamsFromCurve(pub.Curve); params == nil { - err = ErrUnsupportedECIESParameters - return - } - } - R, err := GenerateKey(rand, pub.Curve, params) - if err != nil { - return - } - - hash := params.Hash() - z, err := R.GenerateShared(pub, params.KeyLen, params.KeyLen) - if err != nil { - return - } - K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen) - if err != nil { - return - } - Ke := K[:params.KeyLen] - Km := K[params.KeyLen:] - hash.Write(Km) - Km = hash.Sum(nil) - hash.Reset() - - em, err := symEncrypt(rand, params, Ke, m) - if err != nil || len(em) <= params.BlockSize { - return - } - - d := messageTag(params.Hash, Km, em, s2) - - Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y) - ct = make([]byte, len(Rb)+len(em)+len(d)) - copy(ct, Rb) - copy(ct[len(Rb):], em) - copy(ct[len(Rb)+len(em):], d) - return -} - -// Decrypt decrypts an ECIES ciphertext. -func (prv *PrivateKey) Decrypt(rand io.Reader, c, s1, s2 []byte) (m []byte, err error) { - if c == nil || len(c) == 0 { - err = ErrInvalidMessage - return - } - params := prv.PublicKey.Params - if params == nil { - if params = ParamsFromCurve(prv.PublicKey.Curve); params == nil { - err = ErrUnsupportedECIESParameters - return - } - } - hash := params.Hash() - - var ( - rLen int - hLen int = hash.Size() - mStart int - mEnd int - ) - - switch c[0] { - case 2, 3, 4: - rLen = ((prv.PublicKey.Curve.Params().BitSize + 7) / 4) - if len(c) < (rLen + hLen + 1) { - err = ErrInvalidMessage - return - } - default: - err = ErrInvalidPublicKey - return - } - - mStart = rLen - mEnd = len(c) - hLen - - R := new(PublicKey) - R.Curve = prv.PublicKey.Curve - R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen]) - if R.X == nil { - err = ErrInvalidPublicKey - return - } - - z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen) - if err != nil { - return - } - - K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen) - if err != nil { - return - } - - Ke := K[:params.KeyLen] - Km := K[params.KeyLen:] - hash.Write(Km) - Km = hash.Sum(nil) - hash.Reset() - - d := messageTag(params.Hash, Km, c[mStart:mEnd], s2) - if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 { - err = ErrInvalidMessage - return - } - - m, err = symDecrypt(rand, params, Ke, c[mStart:mEnd]) - return -} diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/ecies_test.go b/Godeps/_workspace/src/github.com/obscuren/ecies/ecies_test.go deleted file mode 100644 index 943e4488e..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/ecies/ecies_test.go +++ /dev/null @@ -1,489 +0,0 @@ -package ecies - -import ( - "bytes" - "crypto/elliptic" - "crypto/rand" - "crypto/sha256" - "flag" - "fmt" - "io/ioutil" - "testing" -) - -var dumpEnc bool - -func init() { - flDump := flag.Bool("dump", false, "write encrypted test message to file") - flag.Parse() - dumpEnc = *flDump -} - -// Ensure the KDF generates appropriately sized keys. -func TestKDF(t *testing.T) { - msg := []byte("Hello, world") - h := sha256.New() - - k, err := concatKDF(h, msg, nil, 64) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - if len(k) != 64 { - fmt.Printf("KDF: generated key is the wrong size (%d instead of 64\n", - len(k)) - t.FailNow() - } -} - -var skLen int -var ErrBadSharedKeys = fmt.Errorf("ecies: shared keys don't match") - -// cmpParams compares a set of ECIES parameters. We assume, as per the -// docs, that AES is the only supported symmetric encryption algorithm. -func cmpParams(p1, p2 *ECIESParams) bool { - if p1.hashAlgo != p2.hashAlgo { - return false - } else if p1.KeyLen != p2.KeyLen { - return false - } else if p1.BlockSize != p2.BlockSize { - return false - } - return true -} - -// cmpPublic returns true if the two public keys represent the same pojnt. -func cmpPublic(pub1, pub2 PublicKey) bool { - if pub1.X == nil || pub1.Y == nil { - fmt.Println(ErrInvalidPublicKey.Error()) - return false - } - if pub2.X == nil || pub2.Y == nil { - fmt.Println(ErrInvalidPublicKey.Error()) - return false - } - pub1Out := elliptic.Marshal(pub1.Curve, pub1.X, pub1.Y) - pub2Out := elliptic.Marshal(pub2.Curve, pub2.X, pub2.Y) - - return bytes.Equal(pub1Out, pub2Out) -} - -// cmpPrivate returns true if the two private keys are the same. -func cmpPrivate(prv1, prv2 *PrivateKey) bool { - if prv1 == nil || prv1.D == nil { - return false - } else if prv2 == nil || prv2.D == nil { - return false - } else if prv1.D.Cmp(prv2.D) != 0 { - return false - } else { - return cmpPublic(prv1.PublicKey, prv2.PublicKey) - } -} - -// Validate the ECDH component. -func TestSharedKey(t *testing.T) { - prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - skLen = MaxSharedKeyLength(&prv1.PublicKey) / 2 - - prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - sk1, err := prv1.GenerateShared(&prv2.PublicKey, skLen, skLen) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - sk2, err := prv2.GenerateShared(&prv1.PublicKey, skLen, skLen) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - if !bytes.Equal(sk1, sk2) { - fmt.Println(ErrBadSharedKeys.Error()) - t.FailNow() - } -} - -// Verify that the key generation code fails when too much key data is -// requested. -func TestTooBigSharedKey(t *testing.T) { - prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - _, err = prv1.GenerateShared(&prv2.PublicKey, skLen*2, skLen*2) - if err != ErrSharedKeyTooBig { - fmt.Println("ecdh: shared key should be too large for curve") - t.FailNow() - } - - _, err = prv2.GenerateShared(&prv1.PublicKey, skLen*2, skLen*2) - if err != ErrSharedKeyTooBig { - fmt.Println("ecdh: shared key should be too large for curve") - t.FailNow() - } -} - -// Ensure a public key can be successfully marshalled and unmarshalled, and -// that the decoded key is the same as the original. -func TestMarshalPublic(t *testing.T) { - prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - out, err := MarshalPublic(&prv.PublicKey) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - pub, err := UnmarshalPublic(out) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - if !cmpPublic(prv.PublicKey, *pub) { - fmt.Println("ecies: failed to unmarshal public key") - t.FailNow() - } -} - -// Ensure that a private key can be encoded into DER format, and that -// the resulting key is properly parsed back into a public key. -func TestMarshalPrivate(t *testing.T) { - prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - out, err := MarshalPrivate(prv) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - if dumpEnc { - ioutil.WriteFile("test.out", out, 0644) - } - - prv2, err := UnmarshalPrivate(out) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - if !cmpPrivate(prv, prv2) { - fmt.Println("ecdh: private key import failed") - t.FailNow() - } -} - -// Ensure that a private key can be successfully encoded to PEM format, and -// the resulting key is properly parsed back in. -func TestPrivatePEM(t *testing.T) { - prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - out, err := ExportPrivatePEM(prv) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - if dumpEnc { - ioutil.WriteFile("test.key", out, 0644) - } - - prv2, err := ImportPrivatePEM(out) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } else if !cmpPrivate(prv, prv2) { - fmt.Println("ecdh: import from PEM failed") - t.FailNow() - } -} - -// Ensure that a public key can be successfully encoded to PEM format, and -// the resulting key is properly parsed back in. -func TestPublicPEM(t *testing.T) { - prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - out, err := ExportPublicPEM(&prv.PublicKey) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - if dumpEnc { - ioutil.WriteFile("test.pem", out, 0644) - } - - pub2, err := ImportPublicPEM(out) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } else if !cmpPublic(prv.PublicKey, *pub2) { - fmt.Println("ecdh: import from PEM failed") - t.FailNow() - } -} - -// Benchmark the generation of P256 keys. -func BenchmarkGenerateKeyP256(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := GenerateKey(rand.Reader, elliptic.P256(), nil); err != nil { - fmt.Println(err.Error()) - b.FailNow() - } - } -} - -// Benchmark the generation of P256 shared keys. -func BenchmarkGenSharedKeyP256(b *testing.B) { - prv, err := GenerateKey(rand.Reader, elliptic.P256(), nil) - if err != nil { - fmt.Println(err.Error()) - b.FailNow() - } - - for i := 0; i < b.N; i++ { - _, err := prv.GenerateShared(&prv.PublicKey, skLen, skLen) - if err != nil { - fmt.Println(err.Error()) - b.FailNow() - } - } -} - -// Verify that an encrypted message can be successfully decrypted. -func TestEncryptDecrypt(t *testing.T) { - prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - message := []byte("Hello, world.") - ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - if !bytes.Equal(pt, message) { - fmt.Println("ecies: plaintext doesn't match message") - t.FailNow() - } - - _, err = prv1.Decrypt(rand.Reader, ct, nil, nil) - if err == nil { - fmt.Println("ecies: encryption should not have succeeded") - t.FailNow() - } -} - -// TestMarshalEncryption validates the encode/decode produces a valid -// ECIES encryption key. -func TestMarshalEncryption(t *testing.T) { - prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - out, err := MarshalPrivate(prv1) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - prv2, err := UnmarshalPrivate(out) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - message := []byte("Hello, world.") - ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - if !bytes.Equal(pt, message) { - fmt.Println("ecies: plaintext doesn't match message") - t.FailNow() - } - - _, err = prv1.Decrypt(rand.Reader, ct, nil, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - -} - -type testCase struct { - Curve elliptic.Curve - Name string - Expected bool -} - -var testCases = []testCase{ - testCase{ - Curve: elliptic.P224(), - Name: "P224", - Expected: false, - }, - testCase{ - Curve: elliptic.P256(), - Name: "P256", - Expected: true, - }, - testCase{ - Curve: elliptic.P384(), - Name: "P384", - Expected: true, - }, - testCase{ - Curve: elliptic.P521(), - Name: "P521", - Expected: true, - }, -} - -// Test parameter selection for each curve, and that P224 fails automatic -// parameter selection (see README for a discussion of P224). Ensures that -// selecting a set of parameters automatically for the given curve works. -func TestParamSelection(t *testing.T) { - for _, c := range testCases { - testParamSelection(t, c) - } -} - -func testParamSelection(t *testing.T, c testCase) { - params := ParamsFromCurve(c.Curve) - if params == nil && c.Expected { - fmt.Printf("%s (%s)\n", ErrInvalidParams.Error(), c.Name) - t.FailNow() - } else if params != nil && !c.Expected { - fmt.Printf("ecies: parameters should be invalid (%s)\n", - c.Name) - t.FailNow() - } - - prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Printf("%s (%s)\n", err.Error(), c.Name) - t.FailNow() - } - - prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Printf("%s (%s)\n", err.Error(), c.Name) - t.FailNow() - } - - message := []byte("Hello, world.") - ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil) - if err != nil { - fmt.Printf("%s (%s)\n", err.Error(), c.Name) - t.FailNow() - } - - pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil) - if err != nil { - fmt.Printf("%s (%s)\n", err.Error(), c.Name) - t.FailNow() - } - - if !bytes.Equal(pt, message) { - fmt.Printf("ecies: plaintext doesn't match message (%s)\n", - c.Name) - t.FailNow() - } - - _, err = prv1.Decrypt(rand.Reader, ct, nil, nil) - if err == nil { - fmt.Printf("ecies: encryption should not have succeeded (%s)\n", - c.Name) - t.FailNow() - } - -} - -// Ensure that the basic public key validation in the decryption operation -// works. -func TestBasicKeyValidation(t *testing.T) { - badBytes := []byte{0, 1, 5, 6, 7, 8, 9} - - prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - message := []byte("Hello, world.") - ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, nil) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - for _, b := range badBytes { - ct[0] = b - _, err := prv.Decrypt(rand.Reader, ct, nil, nil) - if err != ErrInvalidPublicKey { - fmt.Println("ecies: validated an invalid key") - t.FailNow() - } - } -} diff --git a/Godeps/_workspace/src/github.com/obscuren/ecies/params.go b/Godeps/_workspace/src/github.com/obscuren/ecies/params.go deleted file mode 100644 index b968c7c17..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/ecies/params.go +++ /dev/null @@ -1,187 +0,0 @@ -package ecies - -// This file contains parameters for ECIES encryption, specifying the -// symmetric encryption and HMAC parameters. - -import ( - "crypto" - "crypto/aes" - "crypto/cipher" - "crypto/elliptic" - "crypto/sha256" - "crypto/sha512" - "fmt" - "hash" -) - -// The default curve for this package is the NIST P256 curve, which -// provides security equivalent to AES-128. -var DefaultCurve = elliptic.P256() - -var ( - ErrUnsupportedECDHAlgorithm = fmt.Errorf("ecies: unsupported ECDH algorithm") - ErrUnsupportedECIESParameters = fmt.Errorf("ecies: unsupported ECIES parameters") -) - -type ECIESParams struct { - Hash func() hash.Hash // hash function - hashAlgo crypto.Hash - Cipher func([]byte) (cipher.Block, error) // symmetric cipher - BlockSize int // block size of symmetric cipher - KeyLen int // length of symmetric key -} - -// Standard ECIES parameters: -// * ECIES using AES128 and HMAC-SHA-256-16 -// * ECIES using AES256 and HMAC-SHA-256-32 -// * ECIES using AES256 and HMAC-SHA-384-48 -// * ECIES using AES256 and HMAC-SHA-512-64 -var ( - ECIES_AES128_SHA256 *ECIESParams - ECIES_AES256_SHA256 *ECIESParams - ECIES_AES256_SHA384 *ECIESParams - ECIES_AES256_SHA512 *ECIESParams -) - -func init() { - ECIES_AES128_SHA256 = &ECIESParams{ - Hash: sha256.New, - hashAlgo: crypto.SHA256, - Cipher: aes.NewCipher, - BlockSize: aes.BlockSize, - KeyLen: 16, - } - - ECIES_AES256_SHA256 = &ECIESParams{ - Hash: sha256.New, - hashAlgo: crypto.SHA256, - Cipher: aes.NewCipher, - BlockSize: aes.BlockSize, - KeyLen: 32, - } - - ECIES_AES256_SHA384 = &ECIESParams{ - Hash: sha512.New384, - hashAlgo: crypto.SHA384, - Cipher: aes.NewCipher, - BlockSize: aes.BlockSize, - KeyLen: 32, - } - - ECIES_AES256_SHA512 = &ECIESParams{ - Hash: sha512.New, - hashAlgo: crypto.SHA512, - Cipher: aes.NewCipher, - BlockSize: aes.BlockSize, - KeyLen: 32, - } -} - -var paramsFromCurve = map[elliptic.Curve]*ECIESParams{ - elliptic.P256(): ECIES_AES128_SHA256, - elliptic.P384(): ECIES_AES256_SHA384, - elliptic.P521(): ECIES_AES256_SHA512, -} - -func AddParamsForCurve(curve elliptic.Curve, params *ECIESParams) { - paramsFromCurve[curve] = params -} - -// ParamsFromCurve selects parameters optimal for the selected elliptic curve. -// Only the curves P256, P384, and P512 are supported. -func ParamsFromCurve(curve elliptic.Curve) (params *ECIESParams) { - return paramsFromCurve[curve] - - /* - switch curve { - case elliptic.P256(): - return ECIES_AES128_SHA256 - case elliptic.P384(): - return ECIES_AES256_SHA384 - case elliptic.P521(): - return ECIES_AES256_SHA512 - default: - return nil - } - */ -} - -// ASN.1 encode the ECIES parameters relevant to the encryption operations. -func paramsToASNECIES(params *ECIESParams) (asnParams asnECIESParameters) { - if nil == params { - return - } - asnParams.KDF = asnNISTConcatenationKDF - asnParams.MAC = hmacFull - switch params.KeyLen { - case 16: - asnParams.Sym = aes128CTRinECIES - case 24: - asnParams.Sym = aes192CTRinECIES - case 32: - asnParams.Sym = aes256CTRinECIES - } - return -} - -// ASN.1 encode the ECIES parameters relevant to ECDH. -func paramsToASNECDH(params *ECIESParams) (algo asnECDHAlgorithm) { - switch params.hashAlgo { - case crypto.SHA224: - algo = dhSinglePass_stdDH_sha224kdf - case crypto.SHA256: - algo = dhSinglePass_stdDH_sha256kdf - case crypto.SHA384: - algo = dhSinglePass_stdDH_sha384kdf - case crypto.SHA512: - algo = dhSinglePass_stdDH_sha512kdf - } - return -} - -// ASN.1 decode the ECIES parameters relevant to the encryption stage. -func asnECIEStoParams(asnParams asnECIESParameters, params *ECIESParams) { - if !asnParams.KDF.Cmp(asnNISTConcatenationKDF) { - params = nil - return - } else if !asnParams.MAC.Cmp(hmacFull) { - params = nil - return - } - - switch { - case asnParams.Sym.Cmp(aes128CTRinECIES): - params.KeyLen = 16 - params.BlockSize = 16 - params.Cipher = aes.NewCipher - case asnParams.Sym.Cmp(aes192CTRinECIES): - params.KeyLen = 24 - params.BlockSize = 16 - params.Cipher = aes.NewCipher - case asnParams.Sym.Cmp(aes256CTRinECIES): - params.KeyLen = 32 - params.BlockSize = 16 - params.Cipher = aes.NewCipher - default: - params = nil - } -} - -// ASN.1 decode the ECIES parameters relevant to ECDH. -func asnECDHtoParams(asnParams asnECDHAlgorithm, params *ECIESParams) { - if asnParams.Cmp(dhSinglePass_stdDH_sha224kdf) { - params.hashAlgo = crypto.SHA224 - params.Hash = sha256.New224 - } else if asnParams.Cmp(dhSinglePass_stdDH_sha256kdf) { - params.hashAlgo = crypto.SHA256 - params.Hash = sha256.New - } else if asnParams.Cmp(dhSinglePass_stdDH_sha384kdf) { - params.hashAlgo = crypto.SHA384 - params.Hash = sha512.New384 - } else if asnParams.Cmp(dhSinglePass_stdDH_sha512kdf) { - params.hashAlgo = crypto.SHA512 - params.Hash = sha512.New - } else { - params = nil - } -} |