update vendor keybase/go-crypto (#10234)

This commit is contained in:
6543 2020-02-11 19:58:23 +01:00 committed by GitHub
parent 86fdba177a
commit bfd62b6f01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 1062 additions and 769 deletions

View file

@ -83,6 +83,10 @@ func checksumKeyMaterial(key []byte) uint16 {
// private key must have been decrypted first.
// If config is nil, sensible defaults will be used.
func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
if priv == nil || priv.PrivateKey == nil {
return errors.InvalidArgumentError("attempting to decrypt with nil PrivateKey")
}
var err error
var b []byte
@ -90,7 +94,8 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
// padding oracle attacks.
switch priv.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1.bytes)
k := priv.PrivateKey.(*rsa.PrivateKey)
b, err = rsa.DecryptPKCS1v15(config.Random(), k, padToKeySize(&k.PublicKey, e.encryptedMPI1.bytes))
case PubKeyAlgoElGamal:
c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes)
c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes)

View file

@ -17,6 +17,7 @@ import (
"github.com/keybase/go-crypto/cast5"
"github.com/keybase/go-crypto/openpgp/errors"
"github.com/keybase/go-crypto/rsa"
)
// readFull is the same as io.ReadFull except that reading zero bytes returns
@ -413,10 +414,12 @@ const (
PubKeyAlgoElGamal PublicKeyAlgorithm = 16
PubKeyAlgoDSA PublicKeyAlgorithm = 17
// RFC 6637, Section 5.
PubKeyAlgoECDH PublicKeyAlgorithm = 18
PubKeyAlgoECDSA PublicKeyAlgorithm = 19
PubKeyAlgoECDH PublicKeyAlgorithm = 18
PubKeyAlgoECDSA PublicKeyAlgorithm = 19
PubKeyAlgoBadElGamal PublicKeyAlgorithm = 20 // Reserved (deprecated, formerly ElGamal Encrypt or Sign)
// RFC -1
PubKeyAlgoEdDSA PublicKeyAlgorithm = 22
PubKeyAlgoEdDSA PublicKeyAlgorithm = 22
)
// CanEncrypt returns true if it's possible to encrypt a message to a public
@ -507,19 +510,17 @@ func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) {
numBytes := (int(bitLength) + 7) / 8
mpi = make([]byte, numBytes)
_, err = readFull(r, mpi)
return
}
// mpiLength returns the length of the given *big.Int when serialized as an
// MPI.
func mpiLength(n *big.Int) (mpiLengthInBytes int) {
mpiLengthInBytes = 2 /* MPI length */
mpiLengthInBytes += (n.BitLen() + 7) / 8
// According to RFC 4880 3.2. we should check that the MPI has no leading
// zeroes (at least when not an encrypted MPI?), but this implementation
// does generate leading zeroes, so we keep accepting them.
return
}
// writeMPI serializes a big integer to w.
func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) {
// Note that we can produce leading zeroes, in violation of RFC 4880 3.2.
// Implementations seem to be tolerant of them, and stripping them would
// make it complex to guarantee matching re-serialization.
_, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
if err == nil {
_, err = w.Write(mpiBytes)
@ -551,6 +552,18 @@ func writeBig(w io.Writer, i *big.Int) error {
return writeMPI(w, uint16(i.BitLen()), i.Bytes())
}
// padToKeySize left-pads a MPI with zeroes to match the length of the
// specified RSA public.
func padToKeySize(pub *rsa.PublicKey, b []byte) []byte {
k := (pub.N.BitLen() + 7) / 8
if len(b) >= k {
return b
}
bb := make([]byte, k)
copy(bb[len(bb)-len(b):], b)
return bb
}
// CompressionAlgo Represents the different compression algorithms
// supported by OpenPGP (except for BZIP2, which is not currently
// supported). See Section 9.3 of RFC 4880.

View file

@ -44,6 +44,10 @@ type EdDSAPrivateKey struct {
seed parsedMPI
}
func (e *EdDSAPrivateKey) Seed() []byte {
return e.seed.bytes
}
func (e *EdDSAPrivateKey) Sign(digest []byte) (R, S []byte, err error) {
r := bytes.NewReader(e.seed.bytes)
publicKey, privateKey, err := ed25519.GenerateKey(r)
@ -89,6 +93,13 @@ func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateK
return pk
}
func NewECDHPrivateKey(currentTime time.Time, priv *ecdh.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewECDHPublicKey(currentTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
func (pk *PrivateKey) parse(r io.Reader) (err error) {
err = (&pk.PublicKey).parse(r)
if err != nil {
@ -415,8 +426,11 @@ func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
return pk.parseECDHPrivateKey(data)
case PubKeyAlgoEdDSA:
return pk.parseEdDSAPrivateKey(data)
case PubKeyAlgoBadElGamal:
return errors.UnsupportedError("parsing el-gamal sign-or-encrypt privatekeys is unsupported")
default:
return errors.UnsupportedError("cannot parse this private key type")
}
panic("impossible")
}
func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {

View file

@ -27,10 +27,13 @@ import (
"github.com/keybase/go-crypto/openpgp/ecdh"
"github.com/keybase/go-crypto/openpgp/elgamal"
"github.com/keybase/go-crypto/openpgp/errors"
"github.com/keybase/go-crypto/openpgp/s2k"
"github.com/keybase/go-crypto/rsa"
)
var (
// NIST curve P-224
oidCurveP224 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x21}
// NIST curve P-256
oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}
// NIST curve P-384
@ -128,6 +131,8 @@ func (f *ecdsaKey) serialize(w io.Writer) (err error) {
func getCurveByOid(oid []byte) elliptic.Curve {
switch {
case bytes.Equal(oid, oidCurveP224):
return elliptic.P224()
case bytes.Equal(oid, oidCurveP256):
return elliptic.P256()
case bytes.Equal(oid, oidCurveP384):
@ -324,6 +329,30 @@ func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *Public
return pk
}
func getCurveOid(curve elliptic.Curve) (res []byte, err error) {
switch curve {
case elliptic.P224():
res = oidCurveP224
case elliptic.P256():
res = oidCurveP256
case elliptic.P384():
res = oidCurveP384
case elliptic.P521():
res = oidCurveP521
case brainpool.P256r1():
res = oidCurveP256r1
case brainpool.P384r1():
res = oidCurveP384r1
case brainpool.P512r1():
res = oidCurveP512r1
case curve25519.Cv25519():
res = oidCurve25519
default:
err = errors.UnsupportedError("unknown curve")
}
return
}
func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey {
pk := &PublicKey{
CreationTime: creationTime,
@ -331,22 +360,34 @@ func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey
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
case brainpool.P256r1():
pk.ec.oid = oidCurveP256r1
case brainpool.P384r1():
pk.ec.oid = oidCurveP384r1
case brainpool.P512r1():
pk.ec.oid = oidCurveP512r1
oid, _ := getCurveOid(pub.Curve)
pk.ec.oid = oid
bs, bitLen := ecdh.Marshal(pub.Curve, pub.X, pub.Y)
pk.ec.p.bytes = bs
pk.ec.p.bitLength = uint16(bitLen)
pk.setFingerPrintAndKeyId()
return pk
}
func NewECDHPublicKey(creationTime time.Time, pub *ecdh.PublicKey) *PublicKey {
pk := &PublicKey{
CreationTime: creationTime,
PubKeyAlgo: PubKeyAlgoECDH,
PublicKey: pub,
ec: new(ecdsaKey),
}
oid, _ := getCurveOid(pub.Curve)
pk.ec.oid = oid
bs, bitLen := ecdh.Marshal(pub.Curve, pub.X, pub.Y)
pk.ec.p.bytes = bs
pk.ec.p.bitLength = uint16(bitLen)
hashbyte, _ := s2k.HashToHashId(crypto.SHA512)
pk.ecdh = &ecdhKdf{
KdfHash: kdfHashFunction(hashbyte),
KdfAlgo: kdfAlgorithm(CipherAES256),
}
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
@ -377,6 +418,9 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
return err
}
err = pk.edk.check()
if err == nil {
pk.PublicKey = ed25519.PublicKey(pk.edk.p.bytes[1:])
}
case PubKeyAlgoECDSA:
pk.ec = new(ecdsaKey)
if err = pk.ec.parse(r); err != nil {
@ -393,6 +437,14 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
return
}
pk.PublicKey, err = pk.ec.newECDH()
case PubKeyAlgoBadElGamal:
// Key has ElGamal format but nil-implementation - it will
// load but it's not possible to do any operations using this
// key.
err = pk.parseElGamal(r)
if err != nil {
pk.PublicKey = nil
}
default:
err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
}
@ -433,6 +485,8 @@ func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
N: new(big.Int).SetBytes(pk.n.bytes),
E: 0,
}
// Warning: incompatibility with crypto/rsa: keybase fork uses
// int64 public exponents instead of int32.
for i := 0; i < len(pk.e.bytes); i++ {
rsa.E <<= 8
rsa.E |= int64(pk.e.bytes[i])
@ -508,7 +562,7 @@ func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) {
pLength += 2 + uint16(len(pk.q.bytes))
pLength += 2 + uint16(len(pk.g.bytes))
pLength += 2 + uint16(len(pk.y.bytes))
case PubKeyAlgoElGamal:
case PubKeyAlgoElGamal, PubKeyAlgoBadElGamal:
pLength += 2 + uint16(len(pk.p.bytes))
pLength += 2 + uint16(len(pk.g.bytes))
pLength += 2 + uint16(len(pk.y.bytes))
@ -539,7 +593,7 @@ func (pk *PublicKey) Serialize(w io.Writer) (err error) {
length += 2 + len(pk.q.bytes)
length += 2 + len(pk.g.bytes)
length += 2 + len(pk.y.bytes)
case PubKeyAlgoElGamal:
case PubKeyAlgoElGamal, PubKeyAlgoBadElGamal:
length += 2 + len(pk.p.bytes)
length += 2 + len(pk.g.bytes)
length += 2 + len(pk.y.bytes)
@ -587,7 +641,7 @@ func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
return writeMPIs(w, pk.n, pk.e)
case PubKeyAlgoDSA:
return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
case PubKeyAlgoElGamal:
case PubKeyAlgoElGamal, PubKeyAlgoBadElGamal:
return writeMPIs(w, pk.p, pk.g, pk.y)
case PubKeyAlgoECDSA:
return pk.ec.serialize(w)
@ -637,7 +691,7 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
switch pk.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes))
if err != nil {
return errors.SignatureError("RSA verification failure")
}
@ -694,7 +748,7 @@ func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err
switch pk.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
rsaPublicKey := pk.PublicKey.(*rsa.PublicKey)
if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)); err != nil {
return errors.SignatureError("RSA verification failure")
}
return
@ -910,7 +964,7 @@ func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
bitLength = pk.n.bitLength
case PubKeyAlgoDSA:
bitLength = pk.p.bitLength
case PubKeyAlgoElGamal:
case PubKeyAlgoElGamal, PubKeyAlgoBadElGamal:
bitLength = pk.p.bitLength
case PubKeyAlgoECDH:
ecdhPublicKey := pk.PublicKey.(*ecdh.PublicKey)
@ -928,3 +982,12 @@ func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
}
return
}
func (pk *PublicKey) ErrorIfDeprecated() error {
switch pk.PubKeyAlgo {
case PubKeyAlgoBadElGamal:
return errors.DeprecatedKeyError("ElGamal Encrypt or Sign (algo 20) is deprecated")
default:
return nil
}
}

View file

@ -105,6 +105,8 @@ func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) {
return
}
rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)}
// Warning: incompatibility with crypto/rsa: keybase fork uses
// int64 public exponents instead of int32.
for i := 0; i < len(pk.e.bytes); i++ {
rsa.E <<= 8
rsa.E |= int64(pk.e.bytes[i])

View file

@ -10,6 +10,7 @@ import (
"crypto/dsa"
"crypto/ecdsa"
"encoding/binary"
"fmt"
"hash"
"io"
"strconv"
@ -384,18 +385,20 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
err = errors.StructuralError("empty key flags subpacket")
return
}
sig.FlagsValid = true
if subpacket[0]&KeyFlagCertify != 0 {
sig.FlagCertify = true
}
if subpacket[0]&KeyFlagSign != 0 {
sig.FlagSign = true
}
if subpacket[0]&KeyFlagEncryptCommunications != 0 {
sig.FlagEncryptCommunications = true
}
if subpacket[0]&KeyFlagEncryptStorage != 0 {
sig.FlagEncryptStorage = true
if subpacket[0] != 0 {
sig.FlagsValid = true
if subpacket[0]&KeyFlagCertify != 0 {
sig.FlagCertify = true
}
if subpacket[0]&KeyFlagSign != 0 {
sig.FlagSign = true
}
if subpacket[0]&KeyFlagEncryptCommunications != 0 {
sig.FlagEncryptCommunications = true
}
if subpacket[0]&KeyFlagEncryptStorage != 0 {
sig.FlagEncryptStorage = true
}
}
case reasonForRevocationSubpacket:
// Reason For Revocation, section 5.2.3.23
@ -624,6 +627,13 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
return
}
// Parameter check, if this is wrong we will make a signature but
// not serialize it later.
if sig.PubKeyAlgo != priv.PubKeyAlgo {
err = errors.InvalidArgumentError("signature pub key algo does not match priv key")
return
}
switch priv.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
@ -637,26 +647,29 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
digest = digest[:subgroupSize]
}
r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
if err == nil {
sig.DSASigR.bytes = r.Bytes()
sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
sig.DSASigS.bytes = s.Bytes()
sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
if err != nil {
return err
}
sig.DSASigR.bytes = r.Bytes()
sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
sig.DSASigS.bytes = s.Bytes()
sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
case PubKeyAlgoECDSA:
r, s, err := ecdsa.Sign(config.Random(), priv.PrivateKey.(*ecdsa.PrivateKey), digest)
if err == nil {
sig.ECDSASigR = FromBig(r)
sig.ECDSASigS = FromBig(s)
if err != nil {
return err
}
sig.ECDSASigR = FromBig(r)
sig.ECDSASigS = FromBig(s)
case PubKeyAlgoEdDSA:
r, s, err := priv.PrivateKey.(*EdDSAPrivateKey).Sign(digest)
if err == nil {
sig.EdDSASigR = FromBytes(r)
sig.EdDSASigS = FromBytes(s)
if err != nil {
return err
}
sig.EdDSASigR = FromBytes(r)
sig.EdDSASigS = FromBytes(s)
default:
err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
err = errors.UnsupportedError("public key algorithm for signing: " + strconv.Itoa(int(priv.PubKeyAlgo)))
}
return
@ -704,6 +717,28 @@ func (sig *Signature) SignKeyWithSigner(signeePubKey *PublicKey, signerPubKey *P
return sig.Sign(s, nil, config)
}
// CrossSignKey creates PrimaryKeyBinding signature in sig.EmbeddedSignature by
// signing `primary` key's hash using `priv` subkey private key. Primary public
// key is the `signee` here.
func (sig *Signature) CrossSignKey(primary *PublicKey, priv *PrivateKey, config *Config) error {
if len(sig.outSubpackets) > 0 {
return fmt.Errorf("outSubpackets already exists, looks like CrossSignKey was called after Sign")
}
sig.EmbeddedSignature = &Signature{
CreationTime: sig.CreationTime,
SigType: SigTypePrimaryKeyBinding,
PubKeyAlgo: priv.PubKeyAlgo,
Hash: sig.Hash,
}
h, err := keySignatureHash(primary, &priv.PublicKey, sig.Hash)
if err != nil {
return err
}
return sig.EmbeddedSignature.Sign(h, priv, config)
}
// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
// called first.
func (sig *Signature) Serialize(w io.Writer) (err error) {
@ -832,6 +867,14 @@ func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
}
if sig.EmbeddedSignature != nil {
buf := bytes.NewBuffer(nil)
if err := sig.EmbeddedSignature.Serialize(buf); err == nil {
byteContent := buf.Bytes()[2:] // skip 2-byte length header
subpackets = append(subpackets, outputSubpacket{false, embeddedSignatureSubpacket, true, byteContent})
}
}
return
}

View file

@ -91,10 +91,10 @@ func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunc
return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
}
plaintextKey = plaintextKey[1:]
if l := len(plaintextKey); l == 0 || l%cipherFunc.blockSize() != 0 {
return nil, cipherFunc, errors.StructuralError("length of decrypted key not a multiple of block size")
if l, cipherKeySize := len(plaintextKey), cipherFunc.KeySize(); l != cipherFunc.KeySize() {
return nil, cipherFunc, errors.StructuralError("length of decrypted key (" + strconv.Itoa(l) + ") " +
"not equal to cipher keysize (" + strconv.Itoa(cipherKeySize) + ")")
}
return plaintextKey, cipherFunc, nil
}