...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package pgptools
18
19 import (
20 "bytes"
21 "errors"
22 "io"
23
24 "golang.org/x/crypto/openpgp/armor"
25 "golang.org/x/crypto/openpgp/packet"
26 )
27
28 const maxLiteralSize = (1 << 31) - 512
29
30
31 func MergeSignature(w io.Writer, sig []byte, message io.Reader, withArmor bool, filename string) (err error) {
32 var armorer io.WriteCloser = nopCloseWriter{w}
33 if withArmor {
34 armorer, err = armor.Encode(w, "PGP MESSAGE", nil)
35 if err != nil {
36 return err
37 }
38 }
39
40 if err := writeOnePass(armorer, sig); err != nil {
41 return err
42 }
43
44 if size := getSize(message); size >= 0 {
45 if err := serializeLiteral(armorer, message, size, filename); err != nil {
46 return err
47 }
48 } else {
49 litWriter, err := packet.SerializeLiteral(nopCloseWriter{armorer}, true, filename, 0)
50 if err != nil {
51 return err
52 }
53 if _, err := io.Copy(litWriter, message); err != nil {
54 return err
55 }
56 if err := litWriter.Close(); err != nil {
57 return err
58 }
59 }
60
61 if _, err := armorer.Write(sig); err != nil {
62 return err
63 }
64 return armorer.Close()
65 }
66
67
68 func writeOnePass(w io.Writer, sig []byte) error {
69 genpkt, err := packet.Read(bytes.NewReader(sig))
70 if err != nil {
71 return err
72 }
73
74 op := packet.OnePassSignature{IsLast: true}
75 switch pkt := genpkt.(type) {
76 case *packet.SignatureV3:
77 op.SigType = pkt.SigType
78 op.Hash = pkt.Hash
79 op.PubKeyAlgo = pkt.PubKeyAlgo
80 op.KeyId = pkt.IssuerKeyId
81 case *packet.Signature:
82 op.SigType = pkt.SigType
83 op.Hash = pkt.Hash
84 op.PubKeyAlgo = pkt.PubKeyAlgo
85 if pkt.IssuerKeyId != nil {
86 op.KeyId = *pkt.IssuerKeyId
87 }
88 default:
89 return errors.New("not a PGP signature")
90 }
91 return op.Serialize(w)
92 }
93
94
95 func serializeLiteral(w io.Writer, r io.Reader, size int32, filename string) error {
96 if len(filename) > 255 {
97 filename = filename[:255]
98 }
99 var buf bytes.Buffer
100 buf.WriteByte('b')
101 buf.WriteByte(byte(len(filename)))
102 buf.WriteString(filename)
103 buf.Write([]byte{0, 0, 0, 0})
104 packetType := 11
105 psize := int64(size) + int64(buf.Len())
106 if psize > (2<<31)-1 {
107 return errors.New("literal too big")
108 }
109 if err := serializeHeader(w, packetType, int(psize)); err != nil {
110 return err
111 }
112 if _, err := w.Write(buf.Bytes()); err != nil {
113 return err
114 }
115 _, err := io.CopyN(w, r, int64(size))
116 return err
117 }
118
119
120 func getSize(r io.Reader) int32 {
121 seek, ok := r.(io.Seeker)
122 if !ok {
123 return -1
124 }
125 start, err := seek.Seek(0, io.SeekCurrent)
126 if err != nil {
127 return -1
128 }
129 end, err := seek.Seek(0, io.SeekEnd)
130 if err != nil {
131 return -1
132 }
133 seek.Seek(start, io.SeekStart)
134 size := end - start
135 if size > maxLiteralSize {
136 return -1
137 }
138 return int32(size)
139 }
140
141
142
143 func serializeHeader(w io.Writer, ptype int, length int) (err error) {
144 var buf [6]byte
145 var n int
146
147 buf[0] = 0x80 | 0x40 | byte(ptype)
148 if length < 192 {
149 buf[1] = byte(length)
150 n = 2
151 } else if length < 8384 {
152 length -= 192
153 buf[1] = 192 + byte(length>>8)
154 buf[2] = byte(length)
155 n = 3
156 } else {
157 buf[1] = 255
158 buf[2] = byte(length >> 24)
159 buf[3] = byte(length >> 16)
160 buf[4] = byte(length >> 8)
161 buf[5] = byte(length)
162 n = 6
163 }
164
165 _, err = w.Write(buf[:n])
166 return
167 }
168
169 type nopCloseWriter struct {
170 io.Writer
171 }
172
173 func (nopCloseWriter) Close() error {
174 return nil
175 }
176
View as plain text