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 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
|
package domain
import (
"crypto/rand"
"crypto/rsa"
"math/big"
)
// Key provides an interface to an encryption/signing key
type Key interface {
// KeyName returns the KeyName
KeyName() KeyName
// SetKeyNumber sets the key number in the KeyName
SetKeyNumber(number int)
// SetKeyVersion sets the key version in the KeyName
SetKeyVersion(version int)
// Sign signs message
Sign(message []byte) (signature []byte, err error)
// Encrypt encrypts message
Encrypt(message []byte) (encrypted []byte, err error)
// CanSign returns true if the key can be used for signing
CanSign() bool
// CanEncrypt returns true if the key can be used for encryption
CanEncrypt() bool
}
const (
initialKeyNumber = 999
initialKeyVersion = 999
KeyTypeSigning = KeyType("S")
KeyTypeEncryption = KeyType("V")
)
type KeyType string
func (k KeyType) String() string { return string(k) }
// NewPinTanKeyName returns a new KeyName for the pin/tan flow
func NewPinTanKeyName(bankID BankID, userID string, keyType KeyType) *KeyName {
return &KeyName{
BankID: bankID,
UserID: userID,
KeyType: keyType,
KeyNumber: 0,
KeyVersion: 0,
}
}
// NewInitialKeyName represents a KeyName ready to use for initial communication
func NewInitialKeyName(countryCode int, bankID, userID string, keyType KeyType) *KeyName {
return &KeyName{
BankID: BankID{CountryCode: countryCode, ID: bankID},
UserID: userID,
KeyType: keyType,
KeyNumber: initialKeyNumber,
KeyVersion: initialKeyVersion,
}
}
// KeyName provides data about a given key
type KeyName struct {
BankID BankID
UserID string
KeyType KeyType
KeyNumber int
KeyVersion int
}
// IsInitial returns true if the KeyName represents an initial KeyName, false otherwise
func (k *KeyName) IsInitial() bool {
return k.KeyNumber == initialKeyNumber && k.KeyVersion == initialKeyVersion
}
// SetInitial resets the KeyName to reflect an initial KeyName
func (k *KeyName) SetInitial() {
k.KeyNumber = initialKeyNumber
k.KeyVersion = initialKeyVersion
}
// NewPinKey returns a new PinKey
func NewPinKey(pin string, keyName *KeyName) *PinKey {
return &PinKey{pin: pin, keyName: keyName}
}
// PinKey represents a Key used for pin/tan flow
type PinKey struct {
pin string
keyName *KeyName
}
// KeyName returns the KeyName
func (p *PinKey) KeyName() KeyName {
return *p.keyName
}
// SetKeyNumber sets the key number in the KeyName
func (p *PinKey) SetKeyNumber(number int) {
p.keyName.KeyNumber = number
}
// SetKeyVersion sets the key version in the KeyName
func (p *PinKey) SetKeyVersion(version int) {
p.keyName.KeyVersion = version
}
// CanSign returns true if the key can be used for signing
func (p *PinKey) CanSign() bool {
return true
}
// CanEncrypt returns true if the key can be used for encryption
func (p *PinKey) CanEncrypt() bool {
return true
}
// Pin returns the pin within this key
func (p *PinKey) Pin() string {
return p.pin
}
// Sign signs message
func (p *PinKey) Sign(message []byte) ([]byte, error) {
return []byte(p.pin), nil
}
// Encrypt encryptes the message
func (p *PinKey) Encrypt(message []byte) ([]byte, error) {
encMessage := make([]byte, len(message))
// Make a deep copy, just in case
copy(encMessage, message)
return encMessage, nil
}
// Decrypt decrypts the encryptedMessage
func (p *PinKey) Decrypt(encryptedMessage []byte) ([]byte, error) {
decMessage := make([]byte, len(encryptedMessage))
// Make a deep copy, just in case
copy(decMessage, encryptedMessage)
return decMessage, nil
}
// GenerateSigningKey generates a new signing key
func GenerateSigningKey() (*PublicKey, error) {
rsaKey, err := rsa.GenerateKey(rand.Reader, 768)
if err != nil {
return nil, err
}
p := PublicKey{
Type: "S",
Modulus: rsaKey.N.Bytes(),
Exponent: big.NewInt(int64(rsaKey.E)).Bytes(),
rsaPrivateKey: rsaKey,
}
return &p, nil
}
// NewRSAKey returns a new RSA key
func NewRSAKey(pubKey *PublicKey, keyName *KeyName) *RSAKey {
return &RSAKey{PublicKey: pubKey, keyName: keyName}
}
// RSAKey represents a public RSA key which implements the Key interface
type RSAKey struct {
*PublicKey
keyName *KeyName
}
// KeyName returns the KeyName
func (r *RSAKey) KeyName() KeyName {
return *r.keyName
}
// SetKeyNumber sets the key number in the KeyName
func (r *RSAKey) SetKeyNumber(number int) {
r.keyName.KeyNumber = number
}
// SetKeyVersion sets the key version in the KeyName
func (r *RSAKey) SetKeyVersion(version int) {
r.keyName.KeyVersion = version
}
// CanSign returns true if the key can be used for signing
func (r *RSAKey) CanSign() bool {
return r.PublicKey.rsaPrivateKey != nil
}
// CanEncrypt returns true if the key can be used for encryption
func (r *RSAKey) CanEncrypt() bool {
return r.PublicKey.rsaPublicKey != nil
}
// NewEncryptionKey creates a new RSA encryption key
func NewEncryptionKey(modulus, exponent []byte) *PublicKey {
p := &PublicKey{
Type: "V",
}
copy(p.Modulus, modulus)
copy(p.Exponent, exponent)
mod := new(big.Int).SetBytes(modulus)
exp := new(big.Int).SetBytes(exponent)
pubKey := rsa.PublicKey{
N: mod,
E: int(exp.Int64()),
}
p.rsaPublicKey = &pubKey
return p
}
// PublicKey represents a key which can either embed a private or public RSA key
type PublicKey struct {
Type string
Modulus []byte
Exponent []byte
rsaPrivateKey *rsa.PrivateKey
rsaPublicKey *rsa.PublicKey
}
// SigningKey returns the RSA private key to sign with, or nil when not set
func (p *PublicKey) SigningKey() *rsa.PrivateKey {
return p.rsaPrivateKey
}
// Sign signs message with the private key
func (p *PublicKey) Sign(message []byte) ([]byte, error) {
return rsa.SignPKCS1v15(rand.Reader, p.rsaPrivateKey, 0, message)
}
// Encrypt encryptes the message with the public key
func (p *PublicKey) Encrypt(message []byte) ([]byte, error) {
return rsa.EncryptPKCS1v15(rand.Reader, p.rsaPublicKey, message)
}
|