-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathopenpgp.go
109 lines (98 loc) · 3.4 KB
/
openpgp.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
package tpmk
import (
"crypto"
"crypto/rsa"
"fmt"
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/errors"
"golang.org/x/crypto/openpgp/packet"
"golang.org/x/crypto/openpgp/s2k"
)
func NewOpenPGPEntity(name, comment, email string, config *packet.Config, signer crypto.Signer) (*openpgp.Entity, error) {
now := config.Now()
pub, ok := signer.Public().(*rsa.PublicKey)
if !ok {
return nil, errors.InvalidArgumentError("signer must be an rsa key")
}
uid := packet.NewUserId(name, comment, email)
if uid == nil {
return nil, errors.InvalidArgumentError("user id field contained invalid characters")
}
e := &openpgp.Entity{
PrimaryKey: packet.NewRSAPublicKey(now, pub),
PrivateKey: packet.NewSignerPrivateKey(now, signer),
Identities: make(map[string]*openpgp.Identity),
}
isPrimaryId := true
e.Identities[uid.Id] = &openpgp.Identity{
Name: uid.Id,
UserId: uid,
SelfSignature: &packet.Signature{
CreationTime: now,
SigType: packet.SigTypePositiveCert,
PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: config.Hash(),
IsPrimaryId: &isPrimaryId,
FlagsValid: true,
FlagSign: true,
FlagCertify: true,
IssuerKeyId: &e.PrimaryKey.KeyId,
},
}
if err := e.Identities[uid.Id].SelfSignature.SignUserId(uid.Id, e.PrimaryKey, e.PrivateKey, config); err != nil {
return nil, err
}
// Set the PreferredHash for the SelfSignature if one was provided in the config
if config != nil && config.DefaultHash != 0 {
v, ok := s2k.HashToHashId(config.DefaultHash)
if !ok {
return nil, fmt.Errorf("unsupported hash: %s", config.DefaultHash.String())
}
e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{v}
}
// Set DefaultCipher if one was provided
if config != nil && config.DefaultCipher != 0 {
e.Identities[uid.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(config.DefaultCipher)}
}
e.Subkeys = []openpgp.Subkey{
{
PublicKey: packet.NewRSAPublicKey(now, pub),
PrivateKey: packet.NewSignerPrivateKey(now, signer),
Sig: &packet.Signature{
CreationTime: now,
SigType: packet.SigTypeSubkeyBinding,
PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: config.Hash(),
FlagsValid: true,
FlagEncryptStorage: true,
FlagEncryptCommunications: true,
IssuerKeyId: &e.PrimaryKey.KeyId,
},
},
}
e.Subkeys[0].PublicKey.IsSubkey = true
e.Subkeys[0].PrivateKey.IsSubkey = true
err := e.Subkeys[0].Sig.SignKey(e.Subkeys[0].PublicKey, e.PrivateKey, config)
return e, err
}
// ReadOpenPGPEntity reads a public key and returns an openpgp.Entity with the provided crypto.Signer.
// The returned entity can be used for signing or decryption. The private key must match the primary
// public key.
func ReadOpenPGPEntity(packets *packet.Reader, signer crypto.Signer) (*openpgp.Entity, error) {
e, err := openpgp.ReadEntity(packets)
if err != nil {
return nil, err
}
privateKey := packet.NewSignerPrivateKey(e.PrimaryKey.CreationTime, signer)
if privateKey.KeyId != e.PrimaryKey.KeyId {
return nil, fmt.Errorf("id of private key %q does not match public key %q", privateKey.KeyIdString(), e.PrimaryKey.KeyIdString())
}
e.PrivateKey = privateKey
for i := range e.Subkeys {
if e.Subkeys[i].PublicKey.KeyId == privateKey.KeyId {
e.Subkeys[i].PrivateKey = privateKey
e.Subkeys[i].PrivateKey.IsSubkey = true
}
}
return e, nil
}