diff --git a/glide.lock b/glide.lock index a5119b17..1dd00f01 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 205de0b66ed059a1f10d3fb36c7d465439818123940a9aaa68ddc71cc3bbfddd -updated: 2017-04-17T17:09:48.864562358-07:00 +hash: 7de5ab95677974311285feaa83e24f127bbb4c64a68740bab24d71f491e8b689 +updated: 2017-05-24T15:28:05.291154327-07:00 imports: - name: github.com/ajeddeloh/go-json version: 73d058cf8437a1989030afe571eeab9f90eebbbd @@ -80,7 +80,7 @@ imports: subpackages: - errorutil - name: golang.org/x/crypto - version: 5dc8cb4b8a8eb076cbb5a06bc3b8682c15bdbbd3 + version: 7e9105388ebff089b3f99f0ef676ea55a6da3a7e subpackages: - cast5 - openpgp diff --git a/glide.yaml b/glide.yaml index 0a225866..ca750625 100644 --- a/glide.yaml +++ b/glide.yaml @@ -59,7 +59,7 @@ import: - package: github.com/spf13/cobra version: 65a708cee0a4424f4e353d031ce440643e312f92 - package: golang.org/x/crypto - version: 5dc8cb4b8a8eb076cbb5a06bc3b8682c15bdbbd3 + version: 7e9105388ebff089b3f99f0ef676ea55a6da3a7e subpackages: - cast5 - openpgp diff --git a/vendor/golang.org/x/crypto/openpgp/keys.go b/vendor/golang.org/x/crypto/openpgp/keys.go index bfe32603..68b14c6a 100644 --- a/vendor/golang.org/x/crypto/openpgp/keys.go +++ b/vendor/golang.org/x/crypto/openpgp/keys.go @@ -307,8 +307,6 @@ func readToNextPublicKey(packets *packet.Reader) (err error) { return } } - - panic("unreachable") } // ReadEntity reads an entity (public key, identities, subkeys etc) from the @@ -504,6 +502,12 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err }, } + // If the user passes in a DefaultHash via packet.Config, + // set the PreferredHash for the SelfSignature. + if config != nil && config.DefaultHash != 0 { + e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)} + } + e.Subkeys = make([]Subkey, 1) e.Subkeys[0] = Subkey{ PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey), diff --git a/vendor/golang.org/x/crypto/openpgp/packet/packet.go b/vendor/golang.org/x/crypto/openpgp/packet/packet.go index e2bde111..3eded93f 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/packet.go +++ b/vendor/golang.org/x/crypto/openpgp/packet/packet.go @@ -273,8 +273,6 @@ func consumeAll(r io.Reader) (n int64, err error) { return } } - - panic("unreachable") } // packetType represents the numeric ids of the different OpenPGP packet types. See diff --git a/vendor/golang.org/x/crypto/openpgp/packet/private_key.go b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go index 740a27de..34734cc6 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/private_key.go +++ b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go @@ -6,18 +6,21 @@ package packet import ( "bytes" + "crypto" "crypto/cipher" "crypto/dsa" + "crypto/ecdsa" "crypto/rsa" "crypto/sha1" - "golang.org/x/crypto/openpgp/elgamal" - "golang.org/x/crypto/openpgp/errors" - "golang.org/x/crypto/openpgp/s2k" "io" "io/ioutil" "math/big" "strconv" "time" + + "golang.org/x/crypto/openpgp/elgamal" + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/s2k" ) // PrivateKey represents a possibly encrypted private key. See RFC 4880, @@ -28,7 +31,7 @@ type PrivateKey struct { encryptedData []byte cipher CipherFunction s2k func(out, in []byte) - PrivateKey interface{} // An *rsa.PrivateKey or *dsa.PrivateKey. + PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or a crypto.Signer. sha1Checksum bool iv []byte } @@ -54,6 +57,30 @@ func NewElGamalPrivateKey(currentTime time.Time, priv *elgamal.PrivateKey) *Priv return pk } +func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewECDSAPublicKey(currentTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +// NewSignerPrivateKey creates a sign-only PrivateKey from a crypto.Signer that +// implements RSA or ECDSA. +func NewSignerPrivateKey(currentTime time.Time, signer crypto.Signer) *PrivateKey { + pk := new(PrivateKey) + switch pubkey := signer.Public().(type) { + case rsa.PublicKey: + pk.PublicKey = *NewRSAPublicKey(currentTime, &pubkey) + pk.PubKeyAlgo = PubKeyAlgoRSASignOnly + case ecdsa.PublicKey: + pk.PublicKey = *NewECDSAPublicKey(currentTime, &pubkey) + default: + panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey") + } + pk.PrivateKey = signer + return pk +} + func (pk *PrivateKey) parse(r io.Reader) (err error) { err = (&pk.PublicKey).parse(r) if err != nil { @@ -139,6 +166,8 @@ func (pk *PrivateKey) Serialize(w io.Writer) (err error) { err = serializeDSAPrivateKey(privateKeyBuf, priv) case *elgamal.PrivateKey: err = serializeElGamalPrivateKey(privateKeyBuf, priv) + case *ecdsa.PrivateKey: + err = serializeECDSAPrivateKey(privateKeyBuf, priv) default: err = errors.InvalidArgumentError("unknown private key type") } @@ -198,6 +227,10 @@ func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error { return writeBig(w, priv.X) } +func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error { + return writeBig(w, priv.D) +} + // Decrypt decrypts an encrypted private key using a passphrase. func (pk *PrivateKey) Decrypt(passphrase []byte) error { if !pk.Encrypted { @@ -249,6 +282,8 @@ func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) { return pk.parseDSAPrivateKey(data) case PubKeyAlgoElGamal: return pk.parseElGamalPrivateKey(data) + case PubKeyAlgoECDSA: + return pk.parseECDSAPrivateKey(data) } panic("impossible") } @@ -324,3 +359,22 @@ func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) { return nil } + +func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) { + ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey) + + buf := bytes.NewBuffer(data) + d, _, err := readMPI(buf) + if err != nil { + return + } + + pk.PrivateKey = &ecdsa.PrivateKey{ + PublicKey: *ecdsaPub, + D: new(big.Int).SetBytes(d), + } + pk.Encrypted = false + pk.encryptedData = nil + + return nil +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go index 37a6472e..ead26233 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/public_key.go +++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go @@ -224,6 +224,32 @@ func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *Public return pk } +func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey { + pk := &PublicKey{ + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoECDSA, + PublicKey: pub, + ec: new(ecdsaKey), + } + + switch pub.Curve { + case elliptic.P256(): + pk.ec.oid = oidCurveP256 + case elliptic.P384(): + pk.ec.oid = oidCurveP384 + case elliptic.P521(): + pk.ec.oid = oidCurveP521 + default: + panic("unknown elliptic curve") + } + + pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) + pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes)) + + pk.setFingerPrintAndKeyId() + return pk +} + func (pk *PublicKey) parse(r io.Reader) (err error) { // RFC 4880, section 5.5.2 var buf [6]byte @@ -514,7 +540,6 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro default: return errors.SignatureError("Unsupported public key algorithm used in signature") } - panic("unreachable") } // VerifySignatureV3 returns nil iff sig is a valid signature, made by this @@ -559,7 +584,6 @@ func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err default: panic("shouldn't happen") } - panic("unreachable") } // keySignatureHash returns a Hash of the message that needs to be signed for diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go index 26337f5a..5daf7b6c 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go +++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go @@ -216,7 +216,6 @@ func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (er // V3 public keys only support RSA. panic("shouldn't happen") } - panic("unreachable") } // VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature.go b/vendor/golang.org/x/crypto/openpgp/packet/signature.go index 1f29d3df..6ce0cbed 100644 --- a/vendor/golang.org/x/crypto/openpgp/packet/signature.go +++ b/vendor/golang.org/x/crypto/openpgp/packet/signature.go @@ -8,10 +8,12 @@ import ( "bytes" "crypto" "crypto/dsa" - "crypto/rsa" + "crypto/ecdsa" + "encoding/asn1" "encoding/binary" "hash" "io" + "math/big" "strconv" "time" @@ -515,7 +517,8 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e switch priv.PubKeyAlgo { case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: - sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest) + // supports both *rsa.PrivateKey and crypto.Signer + sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes)) case PubKeyAlgoDSA: dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) @@ -532,6 +535,22 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e sig.DSASigS.bytes = s.Bytes() sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes)) } + case PubKeyAlgoECDSA: + var r, s *big.Int + if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok { + // direct support, avoid asn1 wrapping/unwrapping + r, s, err = ecdsa.Sign(config.Random(), pk, digest) + } else { + var b []byte + b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, nil) + if err == nil { + r, s, err = unwrapECDSASig(b) + } + } + if err == nil { + sig.ECDSASigR = fromBig(r) + sig.ECDSASigS = fromBig(s) + } default: err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) } @@ -539,6 +558,19 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e return } +// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA +// signature. +func unwrapECDSASig(b []byte) (r, s *big.Int, err error) { + var ecsdaSig struct { + R, S *big.Int + } + _, err = asn1.Unmarshal(b, &ecsdaSig) + if err != nil { + return + } + return ecsdaSig.R, ecsdaSig.S, nil +} + // SignUserId computes a signature from priv, asserting that pub is a valid // key for the identity id. On success, the signature is stored in sig. Call // Serialize to write it out. @@ -546,7 +578,7 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error { h, err := userIdSignatureHash(id, pub, sig.Hash) if err != nil { - return nil + return err } return sig.Sign(h, priv, config) } diff --git a/vendor/golang.org/x/crypto/openpgp/read.go b/vendor/golang.org/x/crypto/openpgp/read.go index dfffc398..6ec664f4 100644 --- a/vendor/golang.org/x/crypto/openpgp/read.go +++ b/vendor/golang.org/x/crypto/openpgp/read.go @@ -50,14 +50,15 @@ type MessageDetails struct { // If IsSigned is true and SignedBy is non-zero then the signature will // be verified as UnverifiedBody is read. The signature cannot be // checked until the whole of UnverifiedBody is read so UnverifiedBody - // must be consumed until EOF before the data can trusted. Even if a + // must be consumed until EOF before the data can be trusted. Even if a // message isn't signed (or the signer is unknown) the data may contain // an authentication code that is only checked once UnverifiedBody has // been consumed. Once EOF has been seen, the following fields are // valid. (An authentication code failure is reported as a // SignatureError error when reading from UnverifiedBody.) - SignatureError error // nil if the signature is good. - Signature *packet.Signature // the signature packet itself. + SignatureError error // nil if the signature is good. + Signature *packet.Signature // the signature packet itself, if v4 (default) + SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature decrypted io.ReadCloser } @@ -334,13 +335,15 @@ func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) { } var ok bool - if scr.md.Signature, ok = p.(*packet.Signature); !ok { + if scr.md.Signature, ok = p.(*packet.Signature); ok { + scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) + } else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok { + scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3) + } else { scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature") return } - scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) - // The SymmetricallyEncrypted packet, if any, might have an // unsigned hash of its own. In order to check this we need to // close that Reader. diff --git a/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go b/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go index 0e8641ed..4b9a44ca 100644 --- a/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go +++ b/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go @@ -251,7 +251,7 @@ func HashIdToHash(id byte) (h crypto.Hash, ok bool) { } // HashIdToString returns the name of the hash function corresponding to the -// given OpenPGP hash id, or panics if id is unknown. +// given OpenPGP hash id. func HashIdToString(id byte) (name string, ok bool) { for _, m := range hashToHashIdMapping { if m.id == id { diff --git a/vendor/golang.org/x/crypto/openpgp/write.go b/vendor/golang.org/x/crypto/openpgp/write.go index 15aaa1a0..65a304cc 100644 --- a/vendor/golang.org/x/crypto/openpgp/write.go +++ b/vendor/golang.org/x/crypto/openpgp/write.go @@ -231,7 +231,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint } cipher := packet.CipherFunction(candidateCiphers[0]) - // If the cipher specifed by config is a candidate, we'll use that. + // If the cipher specified by config is a candidate, we'll use that. configuredCipher := config.Cipher() for _, c := range candidateCiphers { cipherFunc := packet.CipherFunction(c)