-
Notifications
You must be signed in to change notification settings - Fork 1
/
licensefile-ed25519.go
127 lines (111 loc) · 3.43 KB
/
licensefile-ed25519.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
package licensefile
import (
"crypto/ed25519"
"crypto/rand"
"crypto/x509"
"encoding/pem"
)
// GenerateKeyPairED25519 creates and returns a new ED25519 private and public key.
func GenerateKeyPairED25519() (private, public []byte, err error) {
//Generate key pair.
pubKey, privKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return
}
//Encode the private key.
x509PrivateKey, err := x509.MarshalPKCS8PrivateKey(privKey)
if err != nil {
return
}
pemBlockPrivateKey := &pem.Block{
Type: "PRIVATE KEY",
Bytes: x509PrivateKey,
}
private = pem.EncodeToMemory(pemBlockPrivateKey)
//Encode the public key.
x509PublicKey, err := x509.MarshalPKIXPublicKey(pubKey)
if err != nil {
return
}
pemBlockPublicKey := &pem.Block{
Type: "PUBLIC KEY",
Bytes: x509PublicKey,
}
public = pem.EncodeToMemory(pemBlockPublicKey)
return
}
// SignED25519 signs File with the provided ED25519 private key. The generated signature
// will be set in the Signature field of File. You would need to call File.Marshal()
// after this func completes to return/serve the license key file. The private key
// must be decrypted, if needed, prior to being provided.
//
// A KeyPairAlgoType is not needed since there is only one version of ED25519 that can
// be used whereas with ECDSA or RSA there are multiple versions (curve, bitsize).
func (f *File) SignED25519(privateKey []byte) (err error) {
//Hash.
h, err := f.hash(KeyPairAlgoED25519)
if err != nil {
return
}
//Sign the hash.
//Decode the private key.
pemBlock, _ := pem.Decode(privateKey)
x509Key, err := x509.ParsePKCS8PrivateKey(pemBlock.Bytes)
if err != nil {
return
}
//Generate signature.
sig := ed25519.Sign(x509Key.(ed25519.PrivateKey), h[:])
if err != nil {
return
}
//Encode the signature and set to the Signature field.
f.encodeSignature(sig)
return
}
// VerifySignatureED25519 checks if a File's signature is valid by checking it against
// the ED25519 public key.
//
// This DOES NOT check if a File is expired. You should call Expired() on the File
// after calling this func.
//
// This uses a copy of the File since need to remove the Signature field prior to
// hashing and verification but we don't want to modify the original File so it can
// be used as it was parsed/unmarshalled.
//
// A KeyPairAlgoType is not needed since there is only one version of ED25519 that can
// be used whereas with ECDSA or RSA there are multiple versions (curve, bitsize).
func (f File) VerifySignatureED25519(publicKey []byte) (err error) {
//Get the decoded signature and remove the signature from the File.
decodedSig, err := f.decodeSignature()
if err != nil {
return
}
f.Signature = ""
//Hash.
h, err := f.hash(KeyPairAlgoED25519)
if err != nil {
return
}
//Decode the public key.
pemBlock, _ := pem.Decode(publicKey)
x509Key, err := x509.ParsePKIXPublicKey(pemBlock.Bytes)
if err != nil {
return
}
//Verify signature.
//Note type conversion for x509Key. ParsePKIXPublicKey returns an interface.
valid := ed25519.Verify(x509Key.(ed25519.PublicKey), h[:], decodedSig)
if !valid {
err = ErrBadSignature
}
return
}
// VerifyED25519 calls VerifySignatureED25519().
//
// Deprecated: This func is here just for legacy situations since the old
// VerifyED25519() func was renamed to VerifySignatureED25519() for better clarity.
// Use VerifySignatureED25519() instead.
func (f *File) VerifyED25519(publicKey []byte) (err error) {
return f.VerifySignatureED25519(publicKey)
}