- // Copyright 2011 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
-
- package packet
-
- import (
- "bytes"
- "crypto/cipher"
- "crypto/dsa"
- "crypto/ecdsa"
- "crypto/sha1"
- "fmt"
- "io"
- "io/ioutil"
- "math/big"
- "strconv"
- "time"
-
- "github.com/keybase/go-crypto/ed25519"
- "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"
- )
-
- // PrivateKey represents a possibly encrypted private key. See RFC 4880,
- // section 5.5.3.
- type PrivateKey struct {
- PublicKey
- Encrypted bool // if true then the private key is unavailable until Decrypt has been called.
- encryptedData []byte
- cipher CipherFunction
- s2k func(out, in []byte)
- PrivateKey interface{} // An *rsa.PrivateKey or *dsa.PrivateKey.
- sha1Checksum bool
- iv []byte
- s2kHeader []byte
- }
-
- type EdDSAPrivateKey struct {
- PrivateKey
- seed parsedMPI
- }
-
- func (e *EdDSAPrivateKey) Sign(digest []byte) (R, S []byte, err error) {
- r := bytes.NewReader(e.seed.bytes)
- publicKey, privateKey, err := ed25519.GenerateKey(r)
- if err != nil {
- return nil, nil, err
- }
-
- if !bytes.Equal(publicKey, e.PublicKey.edk.p.bytes[1:]) { // [1:] because [0] is 0x40 mpi header
- return nil, nil, errors.UnsupportedError("EdDSA: Private key does not match public key.")
- }
-
- sig := ed25519.Sign(privateKey, digest)
-
- sigLen := ed25519.SignatureSize / 2
- return sig[:sigLen], sig[sigLen:], nil
- }
-
- func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
- pk := new(PrivateKey)
- pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey)
- pk.PrivateKey = priv
- return pk
- }
-
- func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
- pk := new(PrivateKey)
- pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey)
- pk.PrivateKey = priv
- return pk
- }
-
- func NewElGamalPrivateKey(currentTime time.Time, priv *elgamal.PrivateKey) *PrivateKey {
- pk := new(PrivateKey)
- pk.PublicKey = *NewElGamalPublicKey(currentTime, &priv.PublicKey)
- pk.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
- }
-
- func (pk *PrivateKey) parse(r io.Reader) (err error) {
- err = (&pk.PublicKey).parse(r)
- if err != nil {
- return
- }
- var buf [1]byte
- _, err = readFull(r, buf[:])
- if err != nil {
- return
- }
-
- s2kType := buf[0]
-
- switch s2kType {
- case 0:
- pk.s2k = nil
- pk.Encrypted = false
- case 254, 255:
- _, err = readFull(r, buf[:])
- if err != nil {
- return
- }
- pk.cipher = CipherFunction(buf[0])
- pk.Encrypted = true
- pk.s2k, err = s2k.Parse(r)
- if err != nil {
- return
- }
- if s2kType == 254 {
- pk.sha1Checksum = true
- }
- // S2K == nil implies that we got a "GNU Dummy" S2K. For instance,
- // because our master secret key is on a USB key in a vault somewhere.
- // In that case, there is no further data to consume here.
- if pk.s2k == nil {
- pk.Encrypted = false
- return
- }
- default:
- return errors.UnsupportedError("deprecated s2k function in private key")
- }
- if pk.Encrypted {
- blockSize := pk.cipher.blockSize()
- if blockSize == 0 {
- return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
- }
- pk.iv = make([]byte, blockSize)
- _, err = readFull(r, pk.iv)
- if err != nil {
- return
- }
- }
-
- pk.encryptedData, err = ioutil.ReadAll(r)
- if err != nil {
- return
- }
-
- if !pk.Encrypted {
- return pk.parsePrivateKey(pk.encryptedData)
- }
-
- return
- }
-
- func mod64kHash(d []byte) uint16 {
- var h uint16
- for _, b := range d {
- h += uint16(b)
- }
- return h
- }
-
- // Encrypt is the counterpart to the Decrypt() method below. It encrypts
- // the private key with the provided passphrase. If config is nil, then
- // the standard, and sensible, defaults apply.
- //
- // A key will be derived from the given passphrase using S2K Specifier
- // Type 3 (Iterated + Salted, see RFC-4880 Sec. 3.7.1.3). This choice
- // is hardcoded in s2k.Serialize(). S2KCount is hardcoded to 0, which is
- // equivalent to 65536. And the hash algorithm for key-derivation can be
- // set with config. The encrypted PrivateKey, using the algorithm specified
- // in config (if provided), is written out to the encryptedData member.
- // When Serialize() is called, this encryptedData member will be
- // serialized, using S2K Usage value of 254, and thus SHA1 checksum.
- func (pk *PrivateKey) Encrypt(passphrase []byte, config *Config) (err error) {
- if pk.PrivateKey == nil {
- return errors.InvalidArgumentError("there is no private key to encrypt")
- }
-
- pk.sha1Checksum = true
- pk.cipher = config.Cipher()
- s2kConfig := s2k.Config{
- Hash: config.Hash(),
- S2KCount: 0,
- }
- s2kBuf := bytes.NewBuffer(nil)
- derivedKey := make([]byte, pk.cipher.KeySize())
- err = s2k.Serialize(s2kBuf, derivedKey, config.Random(), passphrase, &s2kConfig)
- if err != nil {
- return err
- }
-
- pk.s2kHeader = s2kBuf.Bytes()
- // No good way to set pk.s2k but to call s2k.Parse(),
- // even though we have all the information here, but
- // most of the functions needed are private to s2k.
- pk.s2k, err = s2k.Parse(s2kBuf)
- pk.iv = make([]byte, pk.cipher.blockSize())
- if _, err = config.Random().Read(pk.iv); err != nil {
- return err
- }
-
- privateKeyBuf := bytes.NewBuffer(nil)
- if err = pk.serializePrivateKey(privateKeyBuf); err != nil {
- return err
- }
-
- checksum := sha1.Sum(privateKeyBuf.Bytes())
- if _, err = privateKeyBuf.Write(checksum[:]); err != nil {
- return err
- }
-
- pkData := privateKeyBuf.Bytes()
- block := pk.cipher.new(derivedKey)
- pk.encryptedData = make([]byte, len(pkData))
- cfb := cipher.NewCFBEncrypter(block, pk.iv)
- cfb.XORKeyStream(pk.encryptedData, pkData)
- pk.Encrypted = true
- return nil
- }
-
- func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
- buf := bytes.NewBuffer(nil)
- err = pk.PublicKey.serializeWithoutHeaders(buf)
- if err != nil {
- return
- }
-
- privateKeyBuf := bytes.NewBuffer(nil)
-
- if pk.PrivateKey == nil {
- _, err = buf.Write([]byte{
- 254, // SHA-1 Convention
- 9, // Encryption scheme (AES256)
- 101, // GNU Extensions
- 2, // Hash value (SHA1)
- 'G', 'N', 'U', // "GNU" as a string
- 1, // Extension type 1001 (minus 1000)
- })
- } else if pk.Encrypted {
- _, err = buf.Write([]byte{
- 254, // SHA-1 Convention
- byte(pk.cipher), // Encryption scheme
- })
- if err != nil {
- return err
- }
- if _, err = buf.Write(pk.s2kHeader); err != nil {
- return err
- }
- if _, err = buf.Write(pk.iv); err != nil {
- return err
- }
- if _, err = privateKeyBuf.Write(pk.encryptedData); err != nil {
- return err
- }
- } else {
- buf.WriteByte(0 /* no encryption */)
- if err = pk.serializePrivateKey(privateKeyBuf); err != nil {
- return err
- }
- }
-
- ptype := packetTypePrivateKey
- contents := buf.Bytes()
- privateKeyBytes := privateKeyBuf.Bytes()
- if pk.IsSubkey {
- ptype = packetTypePrivateSubkey
- }
- totalLen := len(contents) + len(privateKeyBytes)
- if !pk.Encrypted {
- totalLen += 2
- }
- err = serializeHeader(w, ptype, totalLen)
- if err != nil {
- return
- }
- _, err = w.Write(contents)
- if err != nil {
- return
- }
- _, err = w.Write(privateKeyBytes)
- if err != nil {
- return
- }
-
- if len(privateKeyBytes) > 0 && !pk.Encrypted {
- checksum := mod64kHash(privateKeyBytes)
- var checksumBytes [2]byte
- checksumBytes[0] = byte(checksum >> 8)
- checksumBytes[1] = byte(checksum)
- _, err = w.Write(checksumBytes[:])
- }
-
- return
- }
-
- func (pk *PrivateKey) serializePrivateKey(w io.Writer) (err error) {
- switch priv := pk.PrivateKey.(type) {
- case *rsa.PrivateKey:
- err = serializeRSAPrivateKey(w, priv)
- case *dsa.PrivateKey:
- err = serializeDSAPrivateKey(w, priv)
- case *elgamal.PrivateKey:
- err = serializeElGamalPrivateKey(w, priv)
- case *ecdsa.PrivateKey:
- err = serializeECDSAPrivateKey(w, priv)
- case *ecdh.PrivateKey:
- err = serializeECDHPrivateKey(w, priv)
- case *EdDSAPrivateKey:
- err = serializeEdDSAPrivateKey(w, priv)
- default:
- err = errors.InvalidArgumentError("unknown private key type")
- }
-
- return err
- }
-
- func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
- err := writeBig(w, priv.D)
- if err != nil {
- return err
- }
- err = writeBig(w, priv.Primes[1])
- if err != nil {
- return err
- }
- err = writeBig(w, priv.Primes[0])
- if err != nil {
- return err
- }
- return writeBig(w, priv.Precomputed.Qinv)
- }
-
- func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error {
- return writeBig(w, priv.X)
- }
-
- 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)
- }
-
- func serializeECDHPrivateKey(w io.Writer, priv *ecdh.PrivateKey) error {
- return writeBig(w, priv.X)
- }
-
- func serializeEdDSAPrivateKey(w io.Writer, priv *EdDSAPrivateKey) error {
- return writeMPI(w, priv.seed.bitLength, priv.seed.bytes)
- }
-
- // Decrypt decrypts an encrypted private key using a passphrase.
- func (pk *PrivateKey) Decrypt(passphrase []byte) error {
- if !pk.Encrypted {
- return nil
- }
- // For GNU Dummy S2K, there's no key here, so don't do anything.
- if pk.s2k == nil {
- return nil
- }
-
- key := make([]byte, pk.cipher.KeySize())
- pk.s2k(key, passphrase)
- block := pk.cipher.new(key)
- cfb := cipher.NewCFBDecrypter(block, pk.iv)
-
- data := make([]byte, len(pk.encryptedData))
- cfb.XORKeyStream(data, pk.encryptedData)
-
- if pk.sha1Checksum {
- if len(data) < sha1.Size {
- return errors.StructuralError("truncated private key data")
- }
- h := sha1.New()
- h.Write(data[:len(data)-sha1.Size])
- sum := h.Sum(nil)
- if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
- return errors.StructuralError("private key checksum failure")
- }
- data = data[:len(data)-sha1.Size]
- } else {
- if len(data) < 2 {
- return errors.StructuralError("truncated private key data")
- }
- var sum uint16
- for i := 0; i < len(data)-2; i++ {
- sum += uint16(data[i])
- }
- if data[len(data)-2] != uint8(sum>>8) ||
- data[len(data)-1] != uint8(sum) {
- return errors.StructuralError("private key checksum failure")
- }
- data = data[:len(data)-2]
- }
-
- return pk.parsePrivateKey(data)
- }
-
- func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
- switch pk.PublicKey.PubKeyAlgo {
- case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
- return pk.parseRSAPrivateKey(data)
- case PubKeyAlgoDSA:
- return pk.parseDSAPrivateKey(data)
- case PubKeyAlgoElGamal:
- return pk.parseElGamalPrivateKey(data)
- case PubKeyAlgoECDSA:
- return pk.parseECDSAPrivateKey(data)
- case PubKeyAlgoECDH:
- return pk.parseECDHPrivateKey(data)
- case PubKeyAlgoEdDSA:
- return pk.parseEdDSAPrivateKey(data)
- }
- panic("impossible")
- }
-
- func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
- rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
- rsaPriv := new(rsa.PrivateKey)
- rsaPriv.PublicKey = *rsaPub
-
- buf := bytes.NewBuffer(data)
- d, _, err := readMPI(buf)
- if err != nil {
- return
- }
- p, _, err := readMPI(buf)
- if err != nil {
- return
- }
- q, _, err := readMPI(buf)
- if err != nil {
- return
- }
-
- rsaPriv.D = new(big.Int).SetBytes(d)
- rsaPriv.Primes = make([]*big.Int, 2)
- rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
- rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
- if err := rsaPriv.Validate(); err != nil {
- return err
- }
- rsaPriv.Precompute()
- pk.PrivateKey = rsaPriv
- pk.Encrypted = false
- pk.encryptedData = nil
-
- return nil
- }
-
- func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) {
- dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
- dsaPriv := new(dsa.PrivateKey)
- dsaPriv.PublicKey = *dsaPub
-
- buf := bytes.NewBuffer(data)
- x, _, err := readMPI(buf)
- if err != nil {
- return
- }
-
- dsaPriv.X = new(big.Int).SetBytes(x)
- pk.PrivateKey = dsaPriv
- pk.Encrypted = false
- pk.encryptedData = nil
-
- return nil
- }
-
- func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
- pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
- priv := new(elgamal.PrivateKey)
- priv.PublicKey = *pub
-
- buf := bytes.NewBuffer(data)
- x, _, err := readMPI(buf)
- if err != nil {
- return
- }
-
- priv.X = new(big.Int).SetBytes(x)
- pk.PrivateKey = priv
- pk.Encrypted = false
- pk.encryptedData = nil
-
- return nil
- }
-
- func (pk *PrivateKey) parseECDHPrivateKey(data []byte) (err error) {
- pub := pk.PublicKey.PublicKey.(*ecdh.PublicKey)
- priv := new(ecdh.PrivateKey)
- priv.PublicKey = *pub
-
- buf := bytes.NewBuffer(data)
- d, _, err := readMPI(buf)
- if err != nil {
- return
- }
-
- priv.X = new(big.Int).SetBytes(d)
- pk.PrivateKey = priv
- pk.Encrypted = false
- pk.encryptedData = nil
- return nil
- }
-
- func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
- ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey)
- ecdsaPriv := new(ecdsa.PrivateKey)
- ecdsaPriv.PublicKey = *ecdsaPub
-
- buf := bytes.NewBuffer(data)
- d, _, err := readMPI(buf)
- if err != nil {
- return
- }
-
- ecdsaPriv.D = new(big.Int).SetBytes(d)
- pk.PrivateKey = ecdsaPriv
- pk.Encrypted = false
- pk.encryptedData = nil
-
- return nil
- }
-
- func (pk *PrivateKey) parseEdDSAPrivateKey(data []byte) (err error) {
- eddsaPriv := new(EdDSAPrivateKey)
- eddsaPriv.PublicKey = pk.PublicKey
-
- buf := bytes.NewBuffer(data)
- eddsaPriv.seed.bytes, eddsaPriv.seed.bitLength, err = readMPI(buf)
- if err != nil {
- return err
- }
-
- if bLen := len(eddsaPriv.seed.bytes); bLen != 32 { // 32 bytes private part of ed25519 key.
- return errors.UnsupportedError(fmt.Sprintf("Unexpected EdDSA private key length: %d", bLen))
- }
-
- pk.PrivateKey = eddsaPriv
- pk.Encrypted = false
- pk.encryptedData = nil
-
- return nil
- }
|