forked from ProtonMail/gopenpgp
/
sign_detached.go
128 lines (104 loc) · 3.56 KB
/
sign_detached.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package crypto
import (
"bytes"
"errors"
"io"
"strings"
"time"
"github.com/ProtonMail/gopenpgp/internal"
"golang.org/x/crypto/openpgp"
errorsPGP "golang.org/x/crypto/openpgp/errors"
"golang.org/x/crypto/openpgp/packet"
)
// SignTextDetached creates an armored detached signature of a given string.
func (kr *KeyRing) SignTextDetached(plainText string, passphrase string, trimNewlines bool) (string, error) {
signEntity, err := kr.GetSigningEntity(passphrase)
if err != nil {
return "", err
}
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: pgp.getTimeGenerator()}
if trimNewlines {
plainText = internal.TrimNewlines(plainText)
}
att := strings.NewReader(plainText)
var outBuf bytes.Buffer
//SignText
if err := openpgp.ArmoredDetachSignText(&outBuf, signEntity, att, config); err != nil {
return "", err
}
return outBuf.String(), nil
}
// SignBinDetached creates an armored detached signature of binary data.
func (kr *KeyRing) SignBinDetached(plainData []byte, passphrase string) (string, error) {
//sign with 0x00
signEntity, err := kr.GetSigningEntity(passphrase)
if err != nil {
return "", err
}
config := &packet.Config{DefaultCipher: packet.CipherAES256, Time: pgp.getTimeGenerator()}
att := bytes.NewReader(plainData)
var outBuf bytes.Buffer
//sign bin
if err := openpgp.ArmoredDetachSign(&outBuf, signEntity, att, config); err != nil {
return "", err
}
return outBuf.String(), nil
}
// VerifyTextDetachedSig verifies an armored detached signature given the plaintext as a string.
func (kr *KeyRing) VerifyTextDetachedSig(
signature string, plainText string, verifyTime int64, trimNewlines bool,
) (bool, error) {
if trimNewlines {
plainText = internal.TrimNewlines(plainText)
}
origText := bytes.NewReader(bytes.NewBufferString(plainText).Bytes())
return verifySignature(kr.GetEntities(), origText, signature, verifyTime)
}
// VerifyBinDetachedSig verifies an armored detached signature given the plaintext as binary data.
func (kr *KeyRing) VerifyBinDetachedSig(signature string, plainData []byte, verifyTime int64) (bool, error) {
origText := bytes.NewReader(plainData)
return verifySignature(kr.GetEntities(), origText, signature, verifyTime)
}
// Internal
func verifySignature(
pubKeyEntries openpgp.EntityList, origText *bytes.Reader,
signature string, verifyTime int64,
) (bool, error) {
config := &packet.Config{}
if verifyTime == 0 {
config.Time = func() time.Time {
return time.Unix(0, 0)
}
} else {
config.Time = func() time.Time {
return time.Unix(verifyTime+internal.CreationTimeOffset, 0)
}
}
signatureReader := strings.NewReader(signature)
signer, err := openpgp.CheckArmoredDetachedSignature(pubKeyEntries, origText, signatureReader, config)
if err == errorsPGP.ErrSignatureExpired && signer != nil {
if verifyTime > 0 { // if verifyTime = 0: time check disabled, everything is okay
// Maybe the creation time offset pushed it over the edge
// Retry with the actual verification time
config.Time = func() time.Time {
return time.Unix(verifyTime, 0)
}
_, err = signatureReader.Seek(0, io.SeekStart)
if err != nil {
return false, err
}
signer, err = openpgp.CheckArmoredDetachedSignature(pubKeyEntries, origText, signatureReader, config)
if err != nil {
return false, err
}
}
}
if signer == nil {
return false, errors.New("gopenpgp: signer is empty")
}
// if signer.PrimaryKey.KeyId != signed.PrimaryKey.KeyId {
// // t.Errorf("wrong signer got:%x want:%x", signer.PrimaryKey.KeyId, 0)
// return false, errors.New("signer is nil")
// }
return true, nil
}