aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/golang.org/x/crypto/openpgp/write.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/crypto/openpgp/write.go')
-rw-r--r--vendor/golang.org/x/crypto/openpgp/write.go174
1 files changed, 107 insertions, 67 deletions
diff --git a/vendor/golang.org/x/crypto/openpgp/write.go b/vendor/golang.org/x/crypto/openpgp/write.go
index 65a304c..4ee7178 100644
--- a/vendor/golang.org/x/crypto/openpgp/write.go
+++ b/vendor/golang.org/x/crypto/openpgp/write.go
@@ -164,12 +164,12 @@ func hashToHashId(h crypto.Hash) uint8 {
164 return v 164 return v
165} 165}
166 166
167// Encrypt encrypts a message to a number of recipients and, optionally, signs 167// writeAndSign writes the data as a payload package and, optionally, signs
168// it. hints contains optional information, that is also encrypted, that aids 168// it. hints contains optional information, that is also encrypted,
169// the recipients in processing the message. The resulting WriteCloser must 169// that aids the recipients in processing the message. The resulting
170// be closed after the contents of the file have been written. 170// WriteCloser must be closed after the contents of the file have been
171// If config is nil, sensible defaults will be used. 171// written. If config is nil, sensible defaults will be used.
172func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { 172func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
173 var signer *packet.PrivateKey 173 var signer *packet.PrivateKey
174 if signed != nil { 174 if signed != nil {
175 signKey, ok := signed.signingKey(config.Now()) 175 signKey, ok := signed.signingKey(config.Now())
@@ -185,6 +185,83 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
185 } 185 }
186 } 186 }
187 187
188 var hash crypto.Hash
189 for _, hashId := range candidateHashes {
190 if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() {
191 hash = h
192 break
193 }
194 }
195
196 // If the hash specified by config is a candidate, we'll use that.
197 if configuredHash := config.Hash(); configuredHash.Available() {
198 for _, hashId := range candidateHashes {
199 if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash {
200 hash = h
201 break
202 }
203 }
204 }
205
206 if hash == 0 {
207 hashId := candidateHashes[0]
208 name, ok := s2k.HashIdToString(hashId)
209 if !ok {
210 name = "#" + strconv.Itoa(int(hashId))
211 }
212 return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)")
213 }
214
215 if signer != nil {
216 ops := &packet.OnePassSignature{
217 SigType: packet.SigTypeBinary,
218 Hash: hash,
219 PubKeyAlgo: signer.PubKeyAlgo,
220 KeyId: signer.KeyId,
221 IsLast: true,
222 }
223 if err := ops.Serialize(payload); err != nil {
224 return nil, err
225 }
226 }
227
228 if hints == nil {
229 hints = &FileHints{}
230 }
231
232 w := payload
233 if signer != nil {
234 // If we need to write a signature packet after the literal
235 // data then we need to stop literalData from closing
236 // encryptedData.
237 w = noOpCloser{w}
238
239 }
240 var epochSeconds uint32
241 if !hints.ModTime.IsZero() {
242 epochSeconds = uint32(hints.ModTime.Unix())
243 }
244 literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds)
245 if err != nil {
246 return nil, err
247 }
248
249 if signer != nil {
250 return signatureWriter{payload, literalData, hash, hash.New(), signer, config}, nil
251 }
252 return literalData, nil
253}
254
255// Encrypt encrypts a message to a number of recipients and, optionally, signs
256// it. hints contains optional information, that is also encrypted, that aids
257// the recipients in processing the message. The resulting WriteCloser must
258// be closed after the contents of the file have been written.
259// If config is nil, sensible defaults will be used.
260func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
261 if len(to) == 0 {
262 return nil, errors.InvalidArgumentError("no encryption recipient provided")
263 }
264
188 // These are the possible ciphers that we'll use for the message. 265 // These are the possible ciphers that we'll use for the message.
189 candidateCiphers := []uint8{ 266 candidateCiphers := []uint8{
190 uint8(packet.CipherAES128), 267 uint8(packet.CipherAES128),
@@ -194,6 +271,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
194 // These are the possible hash functions that we'll use for the signature. 271 // These are the possible hash functions that we'll use for the signature.
195 candidateHashes := []uint8{ 272 candidateHashes := []uint8{
196 hashToHashId(crypto.SHA256), 273 hashToHashId(crypto.SHA256),
274 hashToHashId(crypto.SHA384),
197 hashToHashId(crypto.SHA512), 275 hashToHashId(crypto.SHA512),
198 hashToHashId(crypto.SHA1), 276 hashToHashId(crypto.SHA1),
199 hashToHashId(crypto.RIPEMD160), 277 hashToHashId(crypto.RIPEMD160),
@@ -241,33 +319,6 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
241 } 319 }
242 } 320 }
243 321
244 var hash crypto.Hash
245 for _, hashId := range candidateHashes {
246 if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() {
247 hash = h
248 break
249 }
250 }
251
252 // If the hash specified by config is a candidate, we'll use that.
253 if configuredHash := config.Hash(); configuredHash.Available() {
254 for _, hashId := range candidateHashes {
255 if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash {
256 hash = h
257 break
258 }
259 }
260 }
261
262 if hash == 0 {
263 hashId := candidateHashes[0]
264 name, ok := s2k.HashIdToString(hashId)
265 if !ok {
266 name = "#" + strconv.Itoa(int(hashId))
267 }
268 return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)")
269 }
270
271 symKey := make([]byte, cipher.KeySize()) 322 symKey := make([]byte, cipher.KeySize())
272 if _, err := io.ReadFull(config.Random(), symKey); err != nil { 323 if _, err := io.ReadFull(config.Random(), symKey); err != nil {
273 return nil, err 324 return nil, err
@@ -279,49 +330,38 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
279 } 330 }
280 } 331 }
281 332
282 encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) 333 payload, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config)
283 if err != nil { 334 if err != nil {
284 return 335 return
285 } 336 }
286 337
287 if signer != nil { 338 return writeAndSign(payload, candidateHashes, signed, hints, config)
288 ops := &packet.OnePassSignature{ 339}
289 SigType: packet.SigTypeBinary,
290 Hash: hash,
291 PubKeyAlgo: signer.PubKeyAlgo,
292 KeyId: signer.KeyId,
293 IsLast: true,
294 }
295 if err := ops.Serialize(encryptedData); err != nil {
296 return nil, err
297 }
298 }
299 340
300 if hints == nil { 341// Sign signs a message. The resulting WriteCloser must be closed after the
301 hints = &FileHints{} 342// contents of the file have been written. hints contains optional information
343// that aids the recipients in processing the message.
344// If config is nil, sensible defaults will be used.
345func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Config) (input io.WriteCloser, err error) {
346 if signed == nil {
347 return nil, errors.InvalidArgumentError("no signer provided")
302 } 348 }
303 349
304 w := encryptedData 350 // These are the possible hash functions that we'll use for the signature.
305 if signer != nil { 351 candidateHashes := []uint8{
306 // If we need to write a signature packet after the literal 352 hashToHashId(crypto.SHA256),
307 // data then we need to stop literalData from closing 353 hashToHashId(crypto.SHA384),
308 // encryptedData. 354 hashToHashId(crypto.SHA512),
309 w = noOpCloser{encryptedData} 355 hashToHashId(crypto.SHA1),
310 356 hashToHashId(crypto.RIPEMD160),
311 }
312 var epochSeconds uint32
313 if !hints.ModTime.IsZero() {
314 epochSeconds = uint32(hints.ModTime.Unix())
315 }
316 literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds)
317 if err != nil {
318 return nil, err
319 } 357 }
320 358 defaultHashes := candidateHashes[len(candidateHashes)-1:]
321 if signer != nil { 359 preferredHashes := signed.primaryIdentity().SelfSignature.PreferredHash
322 return signatureWriter{encryptedData, literalData, hash, hash.New(), signer, config}, nil 360 if len(preferredHashes) == 0 {
361 preferredHashes = defaultHashes
323 } 362 }
324 return literalData, nil 363 candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
364 return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, config)
325} 365}
326 366
327// signatureWriter hashes the contents of a message while passing it along to 367// signatureWriter hashes the contents of a message while passing it along to