-
Notifications
You must be signed in to change notification settings - Fork 64
/
armor62_signcrypt.go
111 lines (102 loc) · 4.97 KB
/
armor62_signcrypt.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.
package saltpack
import (
"bytes"
"io"
)
var (
// Signcryption has the same frame as encryption
armor62SigncryptionHeaderChecker = armor62EncryptionHeaderChecker
armor62SigncryptionFrameChecker = armor62EncryptionFrameChecker
)
func newSigncryptArmor62SealStream(ciphertext io.Writer, sender SigningSecretKey, receiverBoxKeys []BoxPublicKey, receiverSymmetricKeys []ReceiverSymmetricKey, ephemeralKeyCreator EphemeralKeyCreator, rng signcryptRNG, brand string) (plaintext io.WriteCloser, err error) {
// Note: same "BEGIN SALTPACK ENCRYPTED" visible message type.
enc, err := NewArmor62EncoderStream(ciphertext, MessageTypeEncryption, brand)
if err != nil {
return nil, err
}
out, err := newSigncryptSealStream(enc, sender, receiverBoxKeys, receiverSymmetricKeys, ephemeralKeyCreator, rng)
if err != nil {
return nil, err
}
return closeForwarder([]io.WriteCloser{out, enc}), nil
}
// NewSigncryptArmor62SealStream creates a stream that consumes plaintext data.
// It will write out signcrypted data to the io.Writer passed in as ciphertext.
// The signcryption is from the specified sender, and is signcrypted for the
// given receivers.
//
// The "brand" is the optional "brand" string to put into the header
// and footer.
//
// The ciphertext is additionally armored with the recommended armor62-style format.
//
// If initialization succeeds, returns an io.WriteCloser that accepts
// plaintext data to be signcrypted and a nil error. Otherwise,
// returns nil and the initialization error.
//
// ephemeralKeyCreator should be the last argument; it's the 2nd one
// to preserve the public API.
func NewSigncryptArmor62SealStream(ciphertext io.Writer, ephemeralKeyCreator EphemeralKeyCreator, sender SigningSecretKey, receiverBoxKeys []BoxPublicKey, receiverSymmetricKeys []ReceiverSymmetricKey, brand string) (plaintext io.WriteCloser, err error) {
return newSigncryptArmor62SealStream(ciphertext, sender, receiverBoxKeys, receiverSymmetricKeys, ephemeralKeyCreator, defaultSigncryptRNG{}, brand)
}
func signcryptArmor62Seal(plaintext []byte, sender SigningSecretKey, receiverBoxKeys []BoxPublicKey, receiverSymmetricKeys []ReceiverSymmetricKey, ephemeralKeyCreator EphemeralKeyCreator, rng signcryptRNG, brand string) (string, error) {
var buf bytes.Buffer
enc, err := newSigncryptArmor62SealStream(&buf, sender, receiverBoxKeys, receiverSymmetricKeys, ephemeralKeyCreator, rng, brand)
if err != nil {
return "", err
}
if _, err := enc.Write(plaintext); err != nil {
return "", err
}
if err := enc.Close(); err != nil {
return "", err
}
return buf.String(), nil
}
// SigncryptArmor62Seal is the non-streaming version of NewSigncryptArmor62SealStream, which
// inputs a plaintext (in bytes) and output a ciphertext (as a string).
//
// ephemeralKeyCreator should be the last argument; it's the 2nd one
// to preserve the public API.
func SigncryptArmor62Seal(plaintext []byte, ephemeralKeyCreator EphemeralKeyCreator, sender SigningSecretKey, receiverBoxKeys []BoxPublicKey, receiverSymmetricKeys []ReceiverSymmetricKey, brand string) (string, error) {
return signcryptArmor62Seal(plaintext, sender, receiverBoxKeys, receiverSymmetricKeys, ephemeralKeyCreator, defaultSigncryptRNG{}, brand)
}
// NewDearmor62SigncryptOpenStream makes a new stream that dearmors and decrypts the given
// Reader stream. Pass it a keyring so that it can lookup private and public keys
// as necessary. Returns the MessageKeyInfo recovered during header
// processing, an io.Reader stream from which you can read the plaintext, the armor branding, and
// maybe an error if there was a failure.
func NewDearmor62SigncryptOpenStream(ciphertext io.Reader, keyring SigncryptKeyring, resolver SymmetricKeyResolver) (SigningPublicKey, io.Reader, string, error) {
dearmored, frame, err := NewArmor62DecoderStream(ciphertext, armor62SigncryptionHeaderChecker, armor62SigncryptionFrameChecker)
if err != nil {
return nil, nil, "", err
}
brand, err := frame.GetBrand()
if err != nil {
return nil, nil, "", err
}
mki, r, err := NewSigncryptOpenStream(dearmored, keyring, resolver)
if err != nil {
return mki, nil, "", err
}
return mki, r, brand, nil
}
// Dearmor62SigncryptOpen takes an armor62'ed, encrypted ciphertext and attempts to
// dearmor and decrypt it, using the provided keyring. Checks that the frames in the
// armor are as expected. Returns the sender key recovered during message
// processing, the plaintext (if decryption succeeded), the armor branding, and
// maybe an error if there was a failure.
func Dearmor62SigncryptOpen(ciphertext string, keyring SigncryptKeyring, resolver SymmetricKeyResolver) (SigningPublicKey, []byte, string, error) {
buf := bytes.NewBufferString(ciphertext)
mki, s, brand, err := NewDearmor62SigncryptOpenStream(buf, keyring, resolver)
if err != nil {
return mki, nil, "", err
}
out, err := io.ReadAll(s)
if err != nil {
return mki, nil, "", err
}
return mki, out, brand, nil
}