OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / crypto / openpgp / packet / signature_v3.go
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 }