| 
									
										
										
										
											2016-11-02 18:22:53 +02:00
										 |  |  | // 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 implements parsing and serialization of OpenPGP packets, as | 
					
						
							|  |  |  | // specified in RFC 4880. | 
					
						
							|  |  |  | package packet // import "golang.org/x/crypto/openpgp/packet" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bufio" | 
					
						
							|  |  |  | 	"crypto/aes" | 
					
						
							|  |  |  | 	"crypto/cipher" | 
					
						
							|  |  |  | 	"crypto/des" | 
					
						
							| 
									
										
										
										
											2019-01-04 09:22:59 +02:00
										 |  |  | 	"crypto/rsa" | 
					
						
							| 
									
										
										
										
											2016-11-02 18:22:53 +02:00
										 |  |  | 	"io" | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							| 
									
										
										
										
											2019-01-04 09:22:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"golang.org/x/crypto/cast5" | 
					
						
							|  |  |  | 	"golang.org/x/crypto/openpgp/errors" | 
					
						
							| 
									
										
										
										
											2016-11-02 18:22:53 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // readFull is the same as io.ReadFull except that reading zero bytes returns | 
					
						
							|  |  |  | // ErrUnexpectedEOF rather than EOF. | 
					
						
							|  |  |  | func readFull(r io.Reader, buf []byte) (n int, err error) { | 
					
						
							|  |  |  | 	n, err = io.ReadFull(r, buf) | 
					
						
							|  |  |  | 	if err == io.EOF { | 
					
						
							|  |  |  | 		err = io.ErrUnexpectedEOF | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2. | 
					
						
							|  |  |  | func readLength(r io.Reader) (length int64, isPartial bool, err error) { | 
					
						
							|  |  |  | 	var buf [4]byte | 
					
						
							|  |  |  | 	_, err = readFull(r, buf[:1]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	switch { | 
					
						
							|  |  |  | 	case buf[0] < 192: | 
					
						
							|  |  |  | 		length = int64(buf[0]) | 
					
						
							|  |  |  | 	case buf[0] < 224: | 
					
						
							|  |  |  | 		length = int64(buf[0]-192) << 8 | 
					
						
							|  |  |  | 		_, err = readFull(r, buf[0:1]) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		length += int64(buf[0]) + 192 | 
					
						
							|  |  |  | 	case buf[0] < 255: | 
					
						
							|  |  |  | 		length = int64(1) << (buf[0] & 0x1f) | 
					
						
							|  |  |  | 		isPartial = true | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		_, err = readFull(r, buf[0:4]) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		length = int64(buf[0])<<24 | | 
					
						
							|  |  |  | 			int64(buf[1])<<16 | | 
					
						
							|  |  |  | 			int64(buf[2])<<8 | | 
					
						
							|  |  |  | 			int64(buf[3]) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths. | 
					
						
							|  |  |  | // The continuation lengths are parsed and removed from the stream and EOF is | 
					
						
							|  |  |  | // returned at the end of the packet. See RFC 4880, section 4.2.2.4. | 
					
						
							|  |  |  | type partialLengthReader struct { | 
					
						
							|  |  |  | 	r         io.Reader | 
					
						
							|  |  |  | 	remaining int64 | 
					
						
							|  |  |  | 	isPartial bool | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *partialLengthReader) Read(p []byte) (n int, err error) { | 
					
						
							|  |  |  | 	for r.remaining == 0 { | 
					
						
							|  |  |  | 		if !r.isPartial { | 
					
						
							|  |  |  | 			return 0, io.EOF | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		r.remaining, r.isPartial, err = readLength(r.r) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return 0, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	toRead := int64(len(p)) | 
					
						
							|  |  |  | 	if toRead > r.remaining { | 
					
						
							|  |  |  | 		toRead = r.remaining | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n, err = r.r.Read(p[:int(toRead)]) | 
					
						
							|  |  |  | 	r.remaining -= int64(n) | 
					
						
							|  |  |  | 	if n < int(toRead) && err == io.EOF { | 
					
						
							|  |  |  | 		err = io.ErrUnexpectedEOF | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // partialLengthWriter writes a stream of data using OpenPGP partial lengths. | 
					
						
							|  |  |  | // See RFC 4880, section 4.2.2.4. | 
					
						
							|  |  |  | type partialLengthWriter struct { | 
					
						
							|  |  |  | 	w          io.WriteCloser | 
					
						
							|  |  |  | 	lengthByte [1]byte | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (w *partialLengthWriter) Write(p []byte) (n int, err error) { | 
					
						
							|  |  |  | 	for len(p) > 0 { | 
					
						
							|  |  |  | 		for power := uint(14); power < 32; power-- { | 
					
						
							|  |  |  | 			l := 1 << power | 
					
						
							|  |  |  | 			if len(p) >= l { | 
					
						
							|  |  |  | 				w.lengthByte[0] = 224 + uint8(power) | 
					
						
							|  |  |  | 				_, err = w.w.Write(w.lengthByte[:]) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				var m int | 
					
						
							|  |  |  | 				m, err = w.w.Write(p[:l]) | 
					
						
							|  |  |  | 				n += m | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				p = p[l:] | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (w *partialLengthWriter) Close() error { | 
					
						
							|  |  |  | 	w.lengthByte[0] = 0 | 
					
						
							|  |  |  | 	_, err := w.w.Write(w.lengthByte[:]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return w.w.Close() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the | 
					
						
							|  |  |  | // underlying Reader returns EOF before the limit has been reached. | 
					
						
							|  |  |  | type spanReader struct { | 
					
						
							|  |  |  | 	r io.Reader | 
					
						
							|  |  |  | 	n int64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (l *spanReader) Read(p []byte) (n int, err error) { | 
					
						
							|  |  |  | 	if l.n <= 0 { | 
					
						
							|  |  |  | 		return 0, io.EOF | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if int64(len(p)) > l.n { | 
					
						
							|  |  |  | 		p = p[0:l.n] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	n, err = l.r.Read(p) | 
					
						
							|  |  |  | 	l.n -= int64(n) | 
					
						
							|  |  |  | 	if l.n > 0 && err == io.EOF { | 
					
						
							|  |  |  | 		err = io.ErrUnexpectedEOF | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // readHeader parses a packet header and returns an io.Reader which will return | 
					
						
							|  |  |  | // the contents of the packet. See RFC 4880, section 4.2. | 
					
						
							|  |  |  | func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) { | 
					
						
							|  |  |  | 	var buf [4]byte | 
					
						
							|  |  |  | 	_, err = io.ReadFull(r, buf[:1]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if buf[0]&0x80 == 0 { | 
					
						
							|  |  |  | 		err = errors.StructuralError("tag byte does not have MSB set") | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if buf[0]&0x40 == 0 { | 
					
						
							|  |  |  | 		// Old format packet | 
					
						
							|  |  |  | 		tag = packetType((buf[0] & 0x3f) >> 2) | 
					
						
							|  |  |  | 		lengthType := buf[0] & 3 | 
					
						
							|  |  |  | 		if lengthType == 3 { | 
					
						
							|  |  |  | 			length = -1 | 
					
						
							|  |  |  | 			contents = r | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		lengthBytes := 1 << lengthType | 
					
						
							|  |  |  | 		_, err = readFull(r, buf[0:lengthBytes]) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for i := 0; i < lengthBytes; i++ { | 
					
						
							|  |  |  | 			length <<= 8 | 
					
						
							|  |  |  | 			length |= int64(buf[i]) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		contents = &spanReader{r, length} | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// New format packet | 
					
						
							|  |  |  | 	tag = packetType(buf[0] & 0x3f) | 
					
						
							|  |  |  | 	length, isPartial, err := readLength(r) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if isPartial { | 
					
						
							|  |  |  | 		contents = &partialLengthReader{ | 
					
						
							|  |  |  | 			remaining: length, | 
					
						
							|  |  |  | 			isPartial: true, | 
					
						
							|  |  |  | 			r:         r, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		length = -1 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		contents = &spanReader{r, length} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section | 
					
						
							|  |  |  | // 4.2. | 
					
						
							|  |  |  | func serializeHeader(w io.Writer, ptype packetType, length int) (err error) { | 
					
						
							|  |  |  | 	var buf [6]byte | 
					
						
							|  |  |  | 	var n int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	buf[0] = 0x80 | 0x40 | byte(ptype) | 
					
						
							|  |  |  | 	if length < 192 { | 
					
						
							|  |  |  | 		buf[1] = byte(length) | 
					
						
							|  |  |  | 		n = 2 | 
					
						
							|  |  |  | 	} else if length < 8384 { | 
					
						
							|  |  |  | 		length -= 192 | 
					
						
							|  |  |  | 		buf[1] = 192 + byte(length>>8) | 
					
						
							|  |  |  | 		buf[2] = byte(length) | 
					
						
							|  |  |  | 		n = 3 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		buf[1] = 255 | 
					
						
							|  |  |  | 		buf[2] = byte(length >> 24) | 
					
						
							|  |  |  | 		buf[3] = byte(length >> 16) | 
					
						
							|  |  |  | 		buf[4] = byte(length >> 8) | 
					
						
							|  |  |  | 		buf[5] = byte(length) | 
					
						
							|  |  |  | 		n = 6 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = w.Write(buf[:n]) | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // serializeStreamHeader writes an OpenPGP packet header to w where the | 
					
						
							|  |  |  | // length of the packet is unknown. It returns a io.WriteCloser which can be | 
					
						
							|  |  |  | // used to write the contents of the packet. See RFC 4880, section 4.2. | 
					
						
							|  |  |  | func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) { | 
					
						
							|  |  |  | 	var buf [1]byte | 
					
						
							|  |  |  | 	buf[0] = 0x80 | 0x40 | byte(ptype) | 
					
						
							|  |  |  | 	_, err = w.Write(buf[:]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	out = &partialLengthWriter{w: w} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Packet represents an OpenPGP packet. Users are expected to try casting | 
					
						
							|  |  |  | // instances of this interface to specific packet types. | 
					
						
							|  |  |  | type Packet interface { | 
					
						
							|  |  |  | 	parse(io.Reader) error | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // consumeAll reads from the given Reader until error, returning the number of | 
					
						
							|  |  |  | // bytes read. | 
					
						
							|  |  |  | func consumeAll(r io.Reader) (n int64, err error) { | 
					
						
							|  |  |  | 	var m int | 
					
						
							|  |  |  | 	var buf [1024]byte | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		m, err = r.Read(buf[:]) | 
					
						
							|  |  |  | 		n += int64(m) | 
					
						
							|  |  |  | 		if err == io.EOF { | 
					
						
							|  |  |  | 			err = nil | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // packetType represents the numeric ids of the different OpenPGP packet types. See | 
					
						
							|  |  |  | // http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2 | 
					
						
							|  |  |  | type packetType uint8 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	packetTypeEncryptedKey              packetType = 1 | 
					
						
							|  |  |  | 	packetTypeSignature                 packetType = 2 | 
					
						
							|  |  |  | 	packetTypeSymmetricKeyEncrypted     packetType = 3 | 
					
						
							|  |  |  | 	packetTypeOnePassSignature          packetType = 4 | 
					
						
							|  |  |  | 	packetTypePrivateKey                packetType = 5 | 
					
						
							|  |  |  | 	packetTypePublicKey                 packetType = 6 | 
					
						
							|  |  |  | 	packetTypePrivateSubkey             packetType = 7 | 
					
						
							|  |  |  | 	packetTypeCompressed                packetType = 8 | 
					
						
							|  |  |  | 	packetTypeSymmetricallyEncrypted    packetType = 9 | 
					
						
							|  |  |  | 	packetTypeLiteralData               packetType = 11 | 
					
						
							|  |  |  | 	packetTypeUserId                    packetType = 13 | 
					
						
							|  |  |  | 	packetTypePublicSubkey              packetType = 14 | 
					
						
							|  |  |  | 	packetTypeUserAttribute             packetType = 17 | 
					
						
							|  |  |  | 	packetTypeSymmetricallyEncryptedMDC packetType = 18 | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // peekVersion detects the version of a public key packet about to | 
					
						
							|  |  |  | // be read. A bufio.Reader at the original position of the io.Reader | 
					
						
							|  |  |  | // is returned. | 
					
						
							|  |  |  | func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) { | 
					
						
							|  |  |  | 	bufr = bufio.NewReader(r) | 
					
						
							|  |  |  | 	var verBuf []byte | 
					
						
							|  |  |  | 	if verBuf, err = bufr.Peek(1); err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ver = verBuf[0] | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Read reads a single OpenPGP packet from the given io.Reader. If there is an | 
					
						
							|  |  |  | // error parsing a packet, the whole packet is consumed from the input. | 
					
						
							|  |  |  | func Read(r io.Reader) (p Packet, err error) { | 
					
						
							|  |  |  | 	tag, _, contents, err := readHeader(r) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch tag { | 
					
						
							|  |  |  | 	case packetTypeEncryptedKey: | 
					
						
							|  |  |  | 		p = new(EncryptedKey) | 
					
						
							|  |  |  | 	case packetTypeSignature: | 
					
						
							|  |  |  | 		var version byte | 
					
						
							|  |  |  | 		// Detect signature version | 
					
						
							|  |  |  | 		if contents, version, err = peekVersion(contents); err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if version < 4 { | 
					
						
							|  |  |  | 			p = new(SignatureV3) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			p = new(Signature) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case packetTypeSymmetricKeyEncrypted: | 
					
						
							|  |  |  | 		p = new(SymmetricKeyEncrypted) | 
					
						
							|  |  |  | 	case packetTypeOnePassSignature: | 
					
						
							|  |  |  | 		p = new(OnePassSignature) | 
					
						
							|  |  |  | 	case packetTypePrivateKey, packetTypePrivateSubkey: | 
					
						
							|  |  |  | 		pk := new(PrivateKey) | 
					
						
							|  |  |  | 		if tag == packetTypePrivateSubkey { | 
					
						
							|  |  |  | 			pk.IsSubkey = true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		p = pk | 
					
						
							|  |  |  | 	case packetTypePublicKey, packetTypePublicSubkey: | 
					
						
							|  |  |  | 		var version byte | 
					
						
							|  |  |  | 		if contents, version, err = peekVersion(contents); err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		isSubkey := tag == packetTypePublicSubkey | 
					
						
							|  |  |  | 		if version < 4 { | 
					
						
							|  |  |  | 			p = &PublicKeyV3{IsSubkey: isSubkey} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			p = &PublicKey{IsSubkey: isSubkey} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case packetTypeCompressed: | 
					
						
							|  |  |  | 		p = new(Compressed) | 
					
						
							|  |  |  | 	case packetTypeSymmetricallyEncrypted: | 
					
						
							|  |  |  | 		p = new(SymmetricallyEncrypted) | 
					
						
							|  |  |  | 	case packetTypeLiteralData: | 
					
						
							|  |  |  | 		p = new(LiteralData) | 
					
						
							|  |  |  | 	case packetTypeUserId: | 
					
						
							|  |  |  | 		p = new(UserId) | 
					
						
							|  |  |  | 	case packetTypeUserAttribute: | 
					
						
							|  |  |  | 		p = new(UserAttribute) | 
					
						
							|  |  |  | 	case packetTypeSymmetricallyEncryptedMDC: | 
					
						
							|  |  |  | 		se := new(SymmetricallyEncrypted) | 
					
						
							|  |  |  | 		se.MDC = true | 
					
						
							|  |  |  | 		p = se | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		err = errors.UnknownPacketTypeError(tag) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if p != nil { | 
					
						
							|  |  |  | 		err = p.parse(contents) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		consumeAll(contents) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SignatureType represents the different semantic meanings of an OpenPGP | 
					
						
							|  |  |  | // signature. See RFC 4880, section 5.2.1. | 
					
						
							|  |  |  | type SignatureType uint8 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	SigTypeBinary            SignatureType = 0 | 
					
						
							|  |  |  | 	SigTypeText                            = 1 | 
					
						
							|  |  |  | 	SigTypeGenericCert                     = 0x10 | 
					
						
							|  |  |  | 	SigTypePersonaCert                     = 0x11 | 
					
						
							|  |  |  | 	SigTypeCasualCert                      = 0x12 | 
					
						
							|  |  |  | 	SigTypePositiveCert                    = 0x13 | 
					
						
							|  |  |  | 	SigTypeSubkeyBinding                   = 0x18 | 
					
						
							|  |  |  | 	SigTypePrimaryKeyBinding               = 0x19 | 
					
						
							|  |  |  | 	SigTypeDirectSignature                 = 0x1F | 
					
						
							|  |  |  | 	SigTypeKeyRevocation                   = 0x20 | 
					
						
							|  |  |  | 	SigTypeSubkeyRevocation                = 0x28 | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // PublicKeyAlgorithm represents the different public key system specified for | 
					
						
							|  |  |  | // OpenPGP. See | 
					
						
							|  |  |  | // http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12 | 
					
						
							|  |  |  | type PublicKeyAlgorithm uint8 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							| 
									
										
										
										
											2019-01-04 09:22:59 +02:00
										 |  |  | 	PubKeyAlgoRSA     PublicKeyAlgorithm = 1 | 
					
						
							|  |  |  | 	PubKeyAlgoElGamal PublicKeyAlgorithm = 16 | 
					
						
							|  |  |  | 	PubKeyAlgoDSA     PublicKeyAlgorithm = 17 | 
					
						
							| 
									
										
										
										
											2016-11-02 18:22:53 +02:00
										 |  |  | 	// RFC 6637, Section 5. | 
					
						
							|  |  |  | 	PubKeyAlgoECDH  PublicKeyAlgorithm = 18 | 
					
						
							|  |  |  | 	PubKeyAlgoECDSA PublicKeyAlgorithm = 19 | 
					
						
							| 
									
										
										
										
											2019-01-04 09:22:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Deprecated in RFC 4880, Section 13.5. Use key flags instead. | 
					
						
							|  |  |  | 	PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2 | 
					
						
							|  |  |  | 	PubKeyAlgoRSASignOnly    PublicKeyAlgorithm = 3 | 
					
						
							| 
									
										
										
										
											2016-11-02 18:22:53 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // CanEncrypt returns true if it's possible to encrypt a message to a public | 
					
						
							|  |  |  | // key of the given type. | 
					
						
							|  |  |  | func (pka PublicKeyAlgorithm) CanEncrypt() bool { | 
					
						
							|  |  |  | 	switch pka { | 
					
						
							|  |  |  | 	case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal: | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // CanSign returns true if it's possible for a public key of the given type to | 
					
						
							|  |  |  | // sign a message. | 
					
						
							|  |  |  | func (pka PublicKeyAlgorithm) CanSign() bool { | 
					
						
							|  |  |  | 	switch pka { | 
					
						
							|  |  |  | 	case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // CipherFunction represents the different block ciphers specified for OpenPGP. See | 
					
						
							|  |  |  | // http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13 | 
					
						
							|  |  |  | type CipherFunction uint8 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	Cipher3DES   CipherFunction = 2 | 
					
						
							|  |  |  | 	CipherCAST5  CipherFunction = 3 | 
					
						
							|  |  |  | 	CipherAES128 CipherFunction = 7 | 
					
						
							|  |  |  | 	CipherAES192 CipherFunction = 8 | 
					
						
							|  |  |  | 	CipherAES256 CipherFunction = 9 | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // KeySize returns the key size, in bytes, of cipher. | 
					
						
							|  |  |  | func (cipher CipherFunction) KeySize() int { | 
					
						
							|  |  |  | 	switch cipher { | 
					
						
							|  |  |  | 	case Cipher3DES: | 
					
						
							|  |  |  | 		return 24 | 
					
						
							|  |  |  | 	case CipherCAST5: | 
					
						
							|  |  |  | 		return cast5.KeySize | 
					
						
							|  |  |  | 	case CipherAES128: | 
					
						
							|  |  |  | 		return 16 | 
					
						
							|  |  |  | 	case CipherAES192: | 
					
						
							|  |  |  | 		return 24 | 
					
						
							|  |  |  | 	case CipherAES256: | 
					
						
							|  |  |  | 		return 32 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // blockSize returns the block size, in bytes, of cipher. | 
					
						
							|  |  |  | func (cipher CipherFunction) blockSize() int { | 
					
						
							|  |  |  | 	switch cipher { | 
					
						
							|  |  |  | 	case Cipher3DES: | 
					
						
							|  |  |  | 		return des.BlockSize | 
					
						
							|  |  |  | 	case CipherCAST5: | 
					
						
							|  |  |  | 		return 8 | 
					
						
							|  |  |  | 	case CipherAES128, CipherAES192, CipherAES256: | 
					
						
							|  |  |  | 		return 16 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // new returns a fresh instance of the given cipher. | 
					
						
							|  |  |  | func (cipher CipherFunction) new(key []byte) (block cipher.Block) { | 
					
						
							|  |  |  | 	switch cipher { | 
					
						
							|  |  |  | 	case Cipher3DES: | 
					
						
							|  |  |  | 		block, _ = des.NewTripleDESCipher(key) | 
					
						
							|  |  |  | 	case CipherCAST5: | 
					
						
							|  |  |  | 		block, _ = cast5.NewCipher(key) | 
					
						
							|  |  |  | 	case CipherAES128, CipherAES192, CipherAES256: | 
					
						
							|  |  |  | 		block, _ = aes.NewCipher(key) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // readMPI reads a big integer from r. The bit length returned is the bit | 
					
						
							|  |  |  | // length that was specified in r. This is preserved so that the integer can be | 
					
						
							|  |  |  | // reserialized exactly. | 
					
						
							|  |  |  | func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) { | 
					
						
							|  |  |  | 	var buf [2]byte | 
					
						
							|  |  |  | 	_, err = readFull(r, buf[0:]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	bitLength = uint16(buf[0])<<8 | uint16(buf[1]) | 
					
						
							|  |  |  | 	numBytes := (int(bitLength) + 7) / 8 | 
					
						
							|  |  |  | 	mpi = make([]byte, numBytes) | 
					
						
							|  |  |  | 	_, err = readFull(r, mpi) | 
					
						
							| 
									
										
										
										
											2019-01-04 09:22:59 +02:00
										 |  |  | 	// 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. | 
					
						
							| 
									
										
										
										
											2016-11-02 18:22:53 +02:00
										 |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // writeMPI serializes a big integer to w. | 
					
						
							|  |  |  | func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) { | 
					
						
							| 
									
										
										
										
											2019-01-04 09:22:59 +02:00
										 |  |  | 	// 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. | 
					
						
							| 
									
										
										
										
											2016-11-02 18:22:53 +02:00
										 |  |  | 	_, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)}) | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		_, err = w.Write(mpiBytes) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // writeBig serializes a *big.Int to w. | 
					
						
							|  |  |  | func writeBig(w io.Writer, i *big.Int) error { | 
					
						
							|  |  |  | 	return writeMPI(w, uint16(i.BitLen()), i.Bytes()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-04 09:22:59 +02:00
										 |  |  | // 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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-02 18:22:53 +02:00
										 |  |  | // CompressionAlgo Represents the different compression algorithms | 
					
						
							|  |  |  | // supported by OpenPGP (except for BZIP2, which is not currently | 
					
						
							|  |  |  | // supported). See Section 9.3 of RFC 4880. | 
					
						
							|  |  |  | type CompressionAlgo uint8 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	CompressionNone CompressionAlgo = 0 | 
					
						
							|  |  |  | 	CompressionZIP  CompressionAlgo = 1 | 
					
						
							|  |  |  | 	CompressionZLIB CompressionAlgo = 2 | 
					
						
							|  |  |  | ) |