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 (
	
	
	
	
	
	
	
	
	
	
	
	

	
	
	
)
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|dsa|ecdsa}.PrivateKey or crypto.Signer/crypto.Decrypter (Decryptor RSA only).
	sha1Checksum  bool
	iv            []byte
}

func ( time.Time,  *rsa.PrivateKey) *PrivateKey {
	 := new(PrivateKey)
	.PublicKey = *NewRSAPublicKey(, &.PublicKey)
	.PrivateKey = 
	return 
}

func ( time.Time,  *dsa.PrivateKey) *PrivateKey {
	 := new(PrivateKey)
	.PublicKey = *NewDSAPublicKey(, &.PublicKey)
	.PrivateKey = 
	return 
}

func ( time.Time,  *elgamal.PrivateKey) *PrivateKey {
	 := new(PrivateKey)
	.PublicKey = *NewElGamalPublicKey(, &.PublicKey)
	.PrivateKey = 
	return 
}

func ( time.Time,  *ecdsa.PrivateKey) *PrivateKey {
	 := new(PrivateKey)
	.PublicKey = *NewECDSAPublicKey(, &.PublicKey)
	.PrivateKey = 
	return 
}
NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that implements RSA or ECDSA.
func ( time.Time,  crypto.Signer) *PrivateKey {
In general, the public Keys should be used as pointers. We still type-switch on the values, for backwards-compatibility.
	switch pubkey := .Public().(type) {
	case *rsa.PublicKey:
		.PublicKey = *NewRSAPublicKey(, )
	case rsa.PublicKey:
		.PublicKey = *NewRSAPublicKey(, &)
	case *ecdsa.PublicKey:
		.PublicKey = *NewECDSAPublicKey(, )
	case ecdsa.PublicKey:
		.PublicKey = *NewECDSAPublicKey(, &)
	default:
		panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey")
	}
	.PrivateKey = 
	return 
}

func ( *PrivateKey) ( io.Reader) ( error) {
	 = (&.PublicKey).parse()
	if  != nil {
		return
	}
	var  [1]byte
	_,  = readFull(, [:])
	if  != nil {
		return
	}

	 := [0]

	switch  {
	case 0:
		.s2k = nil
		.Encrypted = false
	case 254, 255:
		_,  = readFull(, [:])
		if  != nil {
			return
		}
		.cipher = CipherFunction([0])
		.Encrypted = true
		.s2k,  = s2k.Parse()
		if  != nil {
			return
		}
		if  == 254 {
			.sha1Checksum = true
		}
	default:
		return errors.UnsupportedError("deprecated s2k function in private key")
	}

	if .Encrypted {
		 := .cipher.blockSize()
		if  == 0 {
			return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(.cipher)))
		}
		.iv = make([]byte, )
		_,  = readFull(, .iv)
		if  != nil {
			return
		}
	}

	.encryptedData,  = ioutil.ReadAll()
	if  != nil {
		return
	}

	if !.Encrypted {
		return .parsePrivateKey(.encryptedData)
	}

	return
}

func ( []byte) uint16 {
	var  uint16
	for ,  := range  {
		 += uint16()
	}
	return 
}

TODO(agl): support encrypted private keys
	 := bytes.NewBuffer(nil)
	 = .PublicKey.serializeWithoutHeaders()
	if  != nil {
		return
	}
	.WriteByte(0 /* no encryption */)

	 := bytes.NewBuffer(nil)

	switch priv := .PrivateKey.(type) {
	case *rsa.PrivateKey:
		 = serializeRSAPrivateKey(, )
	case *dsa.PrivateKey:
		 = serializeDSAPrivateKey(, )
	case *elgamal.PrivateKey:
		 = serializeElGamalPrivateKey(, )
	case *ecdsa.PrivateKey:
		 = serializeECDSAPrivateKey(, )
	default:
		 = errors.InvalidArgumentError("unknown private key type")
	}
	if  != nil {
		return
	}

	 := packetTypePrivateKey
	 := .Bytes()
	 := .Bytes()
	if .IsSubkey {
		 = packetTypePrivateSubkey
	}
	 = serializeHeader(, , len()+len()+2)
	if  != nil {
		return
	}
	_,  = .Write()
	if  != nil {
		return
	}
	_,  = .Write()
	if  != nil {
		return
	}

	 := mod64kHash()
	var  [2]byte
	[0] = byte( >> 8)
	[1] = byte()
	_,  = .Write([:])

	return
}

func ( io.Writer,  *rsa.PrivateKey) error {
	 := writeBig(, .D)
	if  != nil {
		return 
	}
	 = writeBig(, .Primes[1])
	if  != nil {
		return 
	}
	 = writeBig(, .Primes[0])
	if  != nil {
		return 
	}
	return writeBig(, .Precomputed.Qinv)
}

func ( io.Writer,  *dsa.PrivateKey) error {
	return writeBig(, .X)
}

func ( io.Writer,  *elgamal.PrivateKey) error {
	return writeBig(, .X)
}

func ( io.Writer,  *ecdsa.PrivateKey) error {
	return writeBig(, .D)
}
Decrypt decrypts an encrypted private key using a passphrase.
func ( *PrivateKey) ( []byte) error {
	if !.Encrypted {
		return nil
	}

	 := make([]byte, .cipher.KeySize())
	.s2k(, )
	 := .cipher.new()
	 := cipher.NewCFBDecrypter(, .iv)

	 := make([]byte, len(.encryptedData))
	.XORKeyStream(, .encryptedData)

	if .sha1Checksum {
		if len() < sha1.Size {
			return errors.StructuralError("truncated private key data")
		}
		 := sha1.New()
		.Write([:len()-sha1.Size])
		 := .Sum(nil)
		if !bytes.Equal(, [len()-sha1.Size:]) {
			return errors.StructuralError("private key checksum failure")
		}
		 = [:len()-sha1.Size]
	} else {
		if len() < 2 {
			return errors.StructuralError("truncated private key data")
		}
		var  uint16
		for  := 0;  < len()-2; ++ {
			 += uint16([])
		}
		if [len()-2] != uint8(>>8) ||
			[len()-1] != uint8() {
			return errors.StructuralError("private key checksum failure")
		}
		 = [:len()-2]
	}

	return .parsePrivateKey()
}

func ( *PrivateKey) ( []byte) ( error) {
	switch .PublicKey.PubKeyAlgo {
	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
		return .parseRSAPrivateKey()
	case PubKeyAlgoDSA:
		return .parseDSAPrivateKey()
	case PubKeyAlgoElGamal:
		return .parseElGamalPrivateKey()
	case PubKeyAlgoECDSA:
		return .parseECDSAPrivateKey()
	}
	panic("impossible")
}

func ( *PrivateKey) ( []byte) ( error) {
	 := .PublicKey.PublicKey.(*rsa.PublicKey)
	 := new(rsa.PrivateKey)
	.PublicKey = *

	 := bytes.NewBuffer()
	, ,  := readMPI()
	if  != nil {
		return
	}
	, ,  := readMPI()
	if  != nil {
		return
	}
	, ,  := readMPI()
	if  != nil {
		return
	}

	.D = new(big.Int).SetBytes()
	.Primes = make([]*big.Int, 2)
	.Primes[0] = new(big.Int).SetBytes()
	.Primes[1] = new(big.Int).SetBytes()
	if  := .Validate();  != nil {
		return 
	}
	.Precompute()
	.PrivateKey = 
	.Encrypted = false
	.encryptedData = nil

	return nil
}

func ( *PrivateKey) ( []byte) ( error) {
	 := .PublicKey.PublicKey.(*dsa.PublicKey)
	 := new(dsa.PrivateKey)
	.PublicKey = *

	 := bytes.NewBuffer()
	, ,  := readMPI()
	if  != nil {
		return
	}

	.X = new(big.Int).SetBytes()
	.PrivateKey = 
	.Encrypted = false
	.encryptedData = nil

	return nil
}

func ( *PrivateKey) ( []byte) ( error) {
	 := .PublicKey.PublicKey.(*elgamal.PublicKey)
	 := new(elgamal.PrivateKey)
	.PublicKey = *

	 := bytes.NewBuffer()
	, ,  := readMPI()
	if  != nil {
		return
	}

	.X = new(big.Int).SetBytes()
	.PrivateKey = 
	.Encrypted = false
	.encryptedData = nil

	return nil
}

func ( *PrivateKey) ( []byte) ( error) {
	 := .PublicKey.PublicKey.(*ecdsa.PublicKey)

	 := bytes.NewBuffer()
	, ,  := readMPI()
	if  != nil {
		return
	}

	.PrivateKey = &ecdsa.PrivateKey{
		PublicKey: *,
		D:         new(big.Int).SetBytes(),
	}
	.Encrypted = false
	.encryptedData = nil

	return nil