565 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			565 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // 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) 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)
 | |
| 	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 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 {
 | |
| 		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)
 | |
| 	case PubKeyAlgoBadElGamal:
 | |
| 		return errors.UnsupportedError("parsing el-gamal sign-or-encrypt privatekeys is unsupported")
 | |
| 	default:
 | |
| 		return errors.UnsupportedError("cannot parse this private key type")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 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
 | |
| }
 |