github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/crypto/openpgp/packet/signature_v3.go (about) 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 "encoding/binary" 10 "fmt" 11 "io" 12 "strconv" 13 "time" 14 15 "golang.org/x/crypto/openpgp/errors" 16 "golang.org/x/crypto/openpgp/s2k" 17 ) 18 19 // SignatureV3 represents older version 3 signatures. These signatures are less secure 20 // than version 4 and should not be used to create new signatures. They are included 21 // here for backwards compatibility to read and validate with older key material. 22 // See RFC 4880, section 5.2.2. 23 type SignatureV3 struct { 24 SigType SignatureType 25 CreationTime time.Time 26 IssuerKeyId uint64 27 PubKeyAlgo PublicKeyAlgorithm 28 Hash crypto.Hash 29 HashTag [2]byte 30 31 RSASignature parsedMPI 32 DSASigR, DSASigS parsedMPI 33 } 34 35 func (sig *SignatureV3) parse(r io.Reader) (err error) { 36 // RFC 4880, section 5.2.2 37 var buf [8]byte 38 if _, err = readFull(r, buf[:1]); err != nil { 39 return 40 } 41 if buf[0] < 2 || buf[0] > 3 { 42 err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) 43 return 44 } 45 if _, err = readFull(r, buf[:1]); err != nil { 46 return 47 } 48 if buf[0] != 5 { 49 err = errors.UnsupportedError( 50 "invalid hashed material length " + strconv.Itoa(int(buf[0]))) 51 return 52 } 53 54 // Read hashed material: signature type + creation time 55 if _, err = readFull(r, buf[:5]); err != nil { 56 return 57 } 58 sig.SigType = SignatureType(buf[0]) 59 t := binary.BigEndian.Uint32(buf[1:5]) 60 sig.CreationTime = time.Unix(int64(t), 0) 61 62 // Eight-octet Key ID of signer. 63 if _, err = readFull(r, buf[:8]); err != nil { 64 return 65 } 66 sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:]) 67 68 // Public-key and hash algorithm 69 if _, err = readFull(r, buf[:2]); err != nil { 70 return 71 } 72 sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0]) 73 switch sig.PubKeyAlgo { 74 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA: 75 default: 76 err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) 77 return 78 } 79 var ok bool 80 if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok { 81 return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) 82 } 83 84 // Two-octet field holding left 16 bits of signed hash value. 85 if _, err = readFull(r, sig.HashTag[:2]); err != nil { 86 return 87 } 88 89 switch sig.PubKeyAlgo { 90 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: 91 sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) 92 case PubKeyAlgoDSA: 93 if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil { 94 return 95 } 96 sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) 97 default: 98 panic("unreachable") 99 } 100 return 101 } 102 103 // Serialize marshals sig to w. Sign, SignUserId or SignKey must have been 104 // called first. 105 func (sig *SignatureV3) Serialize(w io.Writer) (err error) { 106 buf := make([]byte, 8) 107 108 // Write the sig type and creation time 109 buf[0] = byte(sig.SigType) 110 binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix())) 111 if _, err = w.Write(buf[:5]); err != nil { 112 return 113 } 114 115 // Write the issuer long key ID 116 binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId) 117 if _, err = w.Write(buf[:8]); err != nil { 118 return 119 } 120 121 // Write public key algorithm, hash ID, and hash value 122 buf[0] = byte(sig.PubKeyAlgo) 123 hashId, ok := s2k.HashToHashId(sig.Hash) 124 if !ok { 125 return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash)) 126 } 127 buf[1] = hashId 128 copy(buf[2:4], sig.HashTag[:]) 129 if _, err = w.Write(buf[:4]); err != nil { 130 return 131 } 132 133 if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil { 134 return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") 135 } 136 137 switch sig.PubKeyAlgo { 138 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: 139 err = writeMPIs(w, sig.RSASignature) 140 case PubKeyAlgoDSA: 141 err = writeMPIs(w, sig.DSASigR, sig.DSASigS) 142 default: 143 panic("impossible") 144 } 145 return 146 }