-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmessage_asymmetric.go
146 lines (117 loc) · 3.13 KB
/
message_asymmetric.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package emp
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
)
// AsymmetricMessage represents asymmetrically encrypted ET message.
// It implements MessageEncrypter interface
type AsymmetricMessage struct {
EncMessage
rawMessage []byte
hash crypto.Hash
}
// Alg returns Message encryption algorithm
func (m AsymmetricMessage) Alg() string {
return m.Algorithm
}
// EncryptedMessage returns ecrypted part of ET message
func (m AsymmetricMessage) EncryptedMessage() []byte {
return m.Message
}
// Signature returns signature part of ET message
func (m AsymmetricMessage) Signature() []byte {
return m.Sig
}
// Decrypt decrypts received message using given private key bytes
func (m *AsymmetricMessage) Decrypt(privateKey []byte) ([]byte, error) {
pk, err := loadPrivateKeyBytes(privateKey)
if err != nil {
return nil, err
}
rawMsgBytes, err := rsa.DecryptOAEP(m.hash.New(), rand.Reader, pk, m.Message, nil)
if err != nil {
return nil, err
}
m.rawMessage = rawMsgBytes
return rawMsgBytes, nil
}
// Encrypt encrypts message to be sent using given private key
func (m *AsymmetricMessage) Encrypt(pubkey []byte) error {
ki, err := loadPublicKeyBytes(pubkey)
if err != nil {
return err
}
pk, ok := ki.(*rsa.PublicKey)
if !ok {
return errors.New("Non RSA public key given")
}
encryptedMessage, err := rsa.EncryptOAEP(m.hash.New(), rand.Reader, pk, m.rawMessage, nil)
if err != nil {
return err
}
m.Message = encryptedMessage
return nil
}
// Sign signs message using given private key
func (m *AsymmetricMessage) Sign(privateKey []byte) error {
if len(m.EncryptedMessage()) == 0 {
return errors.New("Cannot sign unencrypted message")
}
pk, err := loadPrivateKeyBytes(privateKey)
if err != nil {
return err
}
opts := rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthAuto,
}
h := m.hash.New()
h.Write(m.EncryptedMessage())
hashed := h.Sum(nil)
signature, err := rsa.SignPSS(rand.Reader, pk, m.hash, hashed, &opts)
if err != nil {
return err
}
m.Sig = signature
return nil
}
// Verify checks message signature
func (m RSAMessage) Verify(pubkey []byte) error {
ki, err := loadPublicKeyBytes(pubkey)
if err != nil {
return err
}
pk, ok := ki.(*rsa.PublicKey)
if !ok {
return errors.New("Non RSA public key given")
}
opts := rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthAuto,
}
h := m.hash.New()
h.Write(m.EncryptedMessage())
hashed := h.Sum(nil)
return rsa.VerifyPSS(pk, m.hash, hashed[:], m.Signature(), &opts)
}
func loadPrivateKeyBytes(privateKeyBytes []byte) (*rsa.PrivateKey, error) {
block, _ := pem.Decode(privateKeyBytes)
if block == nil {
return nil, errors.New("Failed to parse PEM block containing the private keys")
}
privKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("Can't parse private key: %s", err.Error())
}
return privKey, nil
}
func loadPublicKeyBytes(publicKeyBytes []byte) (crypto.PublicKey, error) {
block, _ := pem.Decode(publicKeyBytes)
if block == nil {
return nil, errors.New("Failed to parse PEM block containing the public key")
}
return x509.ParsePKIXPublicKey(block.Bytes)
}