...

Source file src/golang.org/x/crypto/openpgp/packet/public_key_v3.go

Documentation: golang.org/x/crypto/openpgp/packet

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package packet
     6  
     7  import (
     8  	"crypto"
     9  	"crypto/md5"
    10  	"crypto/rsa"
    11  	"encoding/binary"
    12  	"fmt"
    13  	"hash"
    14  	"io"
    15  	"math/big"
    16  	"strconv"
    17  	"time"
    18  
    19  	"golang.org/x/crypto/openpgp/errors"
    20  )
    21  
    22  // PublicKeyV3 represents older, version 3 public keys. These keys are less secure and
    23  // should not be used for signing or encrypting. They are supported here only for
    24  // parsing version 3 key material and validating signatures.
    25  // See RFC 4880, section 5.5.2.
    26  type PublicKeyV3 struct {
    27  	CreationTime time.Time
    28  	DaysToExpire uint16
    29  	PubKeyAlgo   PublicKeyAlgorithm
    30  	PublicKey    *rsa.PublicKey
    31  	Fingerprint  [16]byte
    32  	KeyId        uint64
    33  	IsSubkey     bool
    34  
    35  	n, e parsedMPI
    36  }
    37  
    38  // newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey.
    39  // Included here for testing purposes only. RFC 4880, section 5.5.2:
    40  // "an implementation MUST NOT generate a V3 key, but MAY accept it."
    41  func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 {
    42  	pk := &PublicKeyV3{
    43  		CreationTime: creationTime,
    44  		PublicKey:    pub,
    45  		n:            fromBig(pub.N),
    46  		e:            fromBig(big.NewInt(int64(pub.E))),
    47  	}
    48  
    49  	pk.setFingerPrintAndKeyId()
    50  	return pk
    51  }
    52  
    53  func (pk *PublicKeyV3) parse(r io.Reader) (err error) {
    54  	// RFC 4880, section 5.5.2
    55  	var buf [8]byte
    56  	if _, err = readFull(r, buf[:]); err != nil {
    57  		return
    58  	}
    59  	if buf[0] < 2 || buf[0] > 3 {
    60  		return errors.UnsupportedError("public key version")
    61  	}
    62  	pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
    63  	pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7])
    64  	pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7])
    65  	switch pk.PubKeyAlgo {
    66  	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
    67  		err = pk.parseRSA(r)
    68  	default:
    69  		err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
    70  	}
    71  	if err != nil {
    72  		return
    73  	}
    74  
    75  	pk.setFingerPrintAndKeyId()
    76  	return
    77  }
    78  
    79  func (pk *PublicKeyV3) setFingerPrintAndKeyId() {
    80  	// RFC 4880, section 12.2
    81  	fingerPrint := md5.New()
    82  	fingerPrint.Write(pk.n.bytes)
    83  	fingerPrint.Write(pk.e.bytes)
    84  	fingerPrint.Sum(pk.Fingerprint[:0])
    85  	pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:])
    86  }
    87  
    88  // parseRSA parses RSA public key material from the given Reader. See RFC 4880,
    89  // section 5.5.2.
    90  func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) {
    91  	if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil {
    92  		return
    93  	}
    94  	if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil {
    95  		return
    96  	}
    97  
    98  	// RFC 4880 Section 12.2 requires the low 8 bytes of the
    99  	// modulus to form the key id.
   100  	if len(pk.n.bytes) < 8 {
   101  		return errors.StructuralError("v3 public key modulus is too short")
   102  	}
   103  	if len(pk.e.bytes) > 3 {
   104  		err = errors.UnsupportedError("large public exponent")
   105  		return
   106  	}
   107  	rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)}
   108  	for i := 0; i < len(pk.e.bytes); i++ {
   109  		rsa.E <<= 8
   110  		rsa.E |= int(pk.e.bytes[i])
   111  	}
   112  	pk.PublicKey = rsa
   113  	return
   114  }
   115  
   116  // SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
   117  // The prefix is used when calculating a signature over this public key. See
   118  // RFC 4880, section 5.2.4.
   119  func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) {
   120  	var pLength uint16
   121  	switch pk.PubKeyAlgo {
   122  	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
   123  		pLength += 2 + uint16(len(pk.n.bytes))
   124  		pLength += 2 + uint16(len(pk.e.bytes))
   125  	default:
   126  		panic("unknown public key algorithm")
   127  	}
   128  	pLength += 6
   129  	w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
   130  	return
   131  }
   132  
   133  func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) {
   134  	length := 8 // 8 byte header
   135  
   136  	switch pk.PubKeyAlgo {
   137  	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
   138  		length += 2 + len(pk.n.bytes)
   139  		length += 2 + len(pk.e.bytes)
   140  	default:
   141  		panic("unknown public key algorithm")
   142  	}
   143  
   144  	packetType := packetTypePublicKey
   145  	if pk.IsSubkey {
   146  		packetType = packetTypePublicSubkey
   147  	}
   148  	if err = serializeHeader(w, packetType, length); err != nil {
   149  		return
   150  	}
   151  	return pk.serializeWithoutHeaders(w)
   152  }
   153  
   154  // serializeWithoutHeaders marshals the PublicKey to w in the form of an
   155  // OpenPGP public key packet, not including the packet header.
   156  func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) {
   157  	var buf [8]byte
   158  	// Version 3
   159  	buf[0] = 3
   160  	// Creation time
   161  	t := uint32(pk.CreationTime.Unix())
   162  	buf[1] = byte(t >> 24)
   163  	buf[2] = byte(t >> 16)
   164  	buf[3] = byte(t >> 8)
   165  	buf[4] = byte(t)
   166  	// Days to expire
   167  	buf[5] = byte(pk.DaysToExpire >> 8)
   168  	buf[6] = byte(pk.DaysToExpire)
   169  	// Public key algorithm
   170  	buf[7] = byte(pk.PubKeyAlgo)
   171  
   172  	if _, err = w.Write(buf[:]); err != nil {
   173  		return
   174  	}
   175  
   176  	switch pk.PubKeyAlgo {
   177  	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
   178  		return writeMPIs(w, pk.n, pk.e)
   179  	}
   180  	return errors.InvalidArgumentError("bad public-key algorithm")
   181  }
   182  
   183  // CanSign returns true iff this public key can generate signatures
   184  func (pk *PublicKeyV3) CanSign() bool {
   185  	return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly
   186  }
   187  
   188  // VerifySignatureV3 returns nil iff sig is a valid signature, made by this
   189  // public key, of the data hashed into signed. signed is mutated by this call.
   190  func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) {
   191  	if !pk.CanSign() {
   192  		return errors.InvalidArgumentError("public key cannot generate signatures")
   193  	}
   194  
   195  	suffix := make([]byte, 5)
   196  	suffix[0] = byte(sig.SigType)
   197  	binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix()))
   198  	signed.Write(suffix)
   199  	hashBytes := signed.Sum(nil)
   200  
   201  	if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
   202  		return errors.SignatureError("hash tag doesn't match")
   203  	}
   204  
   205  	if pk.PubKeyAlgo != sig.PubKeyAlgo {
   206  		return errors.InvalidArgumentError("public key and signature use different algorithms")
   207  	}
   208  
   209  	switch pk.PubKeyAlgo {
   210  	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
   211  		if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
   212  			return errors.SignatureError("RSA verification failure")
   213  		}
   214  		return
   215  	default:
   216  		// V3 public keys only support RSA.
   217  		panic("shouldn't happen")
   218  	}
   219  }
   220  
   221  // VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
   222  // public key, that id is the identity of pub.
   223  func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) {
   224  	h, err := userIdSignatureV3Hash(id, pk, sig.Hash)
   225  	if err != nil {
   226  		return err
   227  	}
   228  	return pk.VerifySignatureV3(h, sig)
   229  }
   230  
   231  // VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this
   232  // public key, of signed.
   233  func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) {
   234  	h, err := keySignatureHash(pk, signed, sig.Hash)
   235  	if err != nil {
   236  		return err
   237  	}
   238  	return pk.VerifySignatureV3(h, sig)
   239  }
   240  
   241  // userIdSignatureV3Hash returns a Hash of the message that needs to be signed
   242  // to assert that pk is a valid key for id.
   243  func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) {
   244  	if !hfn.Available() {
   245  		return nil, errors.UnsupportedError("hash function")
   246  	}
   247  	h = hfn.New()
   248  
   249  	// RFC 4880, section 5.2.4
   250  	pk.SerializeSignaturePrefix(h)
   251  	pk.serializeWithoutHeaders(h)
   252  
   253  	h.Write([]byte(id))
   254  
   255  	return
   256  }
   257  
   258  // KeyIdString returns the public key's fingerprint in capital hex
   259  // (e.g. "6C7EE1B8621CC013").
   260  func (pk *PublicKeyV3) KeyIdString() string {
   261  	return fmt.Sprintf("%X", pk.KeyId)
   262  }
   263  
   264  // KeyIdShortString returns the short form of public key's fingerprint
   265  // in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
   266  func (pk *PublicKeyV3) KeyIdShortString() string {
   267  	return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF)
   268  }
   269  
   270  // BitLength returns the bit length for the given public key.
   271  func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) {
   272  	switch pk.PubKeyAlgo {
   273  	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
   274  		bitLength = pk.n.bitLength
   275  	default:
   276  		err = errors.InvalidArgumentError("bad public-key algorithm")
   277  	}
   278  	return
   279  }
   280  

View as plain text