-
Notifications
You must be signed in to change notification settings - Fork 0
/
rsa.go
159 lines (134 loc) · 3.8 KB
/
rsa.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
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
* Project: Application Security Libraries
* Filename: /rsa.go
* Created Date: Friday September 1st 2023 14:29:32 +0800
* Author: Sallehuddin Abdul Latif (sallehuddin@berrypay.com)
* Company: BerryPay (M) Sdn. Bhd.
* --------------------------------------
* Last Modified: Friday September 1st 2023 14:33:15 +0800
* Modified By: Sallehuddin Abdul Latif (sallehuddin@berrypay.com)
* --------------------------------------
* Copyright (c) 2023 BerryPay (M) Sdn. Bhd.
*/
package appsec
import (
"bufio"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"os"
"path/filepath"
)
var AppPublicKey *rsa.PublicKey
var AppPrivateKey *rsa.PrivateKey
// LoadPrivateKey loads the public key from the given PEM certificate file
//
// If the argument path is empty, the default app.key file on the same directory of executable is assumed to be used
func LoadPrivateKey(path string) error {
// get base directory of the executable
execBinFile, err := os.Executable()
if err != nil {
return err
}
binDir, err := filepath.Abs(filepath.Dir(execBinFile))
if err != nil {
return err
}
pemFilePath := filepath.Join(binDir, "app.key")
if path != "" {
pemFilePath = path
}
privateKeyFile, err := os.Open(pemFilePath)
if err != nil {
return err
}
pemFileInfo, _ := privateKeyFile.Stat()
pemFileSize := pemFileInfo.Size()
pemFileBytes := make([]byte, pemFileSize)
buffer := bufio.NewReader(privateKeyFile)
_, err = buffer.Read(pemFileBytes)
if err != nil {
return err
}
pemBlock, _ := pem.Decode([]byte(pemFileBytes))
privateKeyFile.Close()
AppPrivateKey, err = x509.ParsePKCS1PrivateKey(pemBlock.Bytes)
if err != nil {
return err
}
if err = AppPrivateKey.Validate(); err != nil {
return err
}
AppPublicKey = &AppPrivateKey.PublicKey
return nil
}
// LoadPublicKey loads the public key from the given PEM certificate file
//
// If the argument path is empty, the default app.crt file on the same directory of executable is assumed to be used
func LoadPublicKey(path string) error {
// get base directory of the executable
execBinFile, err := os.Executable()
if err != nil {
return err
}
binDir, err := filepath.Abs(filepath.Dir(execBinFile))
if err != nil {
return err
}
pemFilePath := filepath.Join(binDir, "app.crt")
if path != "" {
pemFilePath = path
}
publicKeyFile, err := os.Open(pemFilePath)
if err != nil {
return err
}
pemFileInfo, _ := publicKeyFile.Stat()
pemFileSize := pemFileInfo.Size()
pemFileBytes := make([]byte, pemFileSize)
buffer := bufio.NewReader(publicKeyFile)
_, err = buffer.Read(pemFileBytes)
if err != nil {
return err
}
pemBlock, _ := pem.Decode([]byte(pemFileBytes))
publicKeyFile.Close()
cert, err := x509.ParseCertificate(pemBlock.Bytes)
if err != nil {
return err
}
AppPublicKey = cert.PublicKey.(*rsa.PublicKey)
return nil
}
// Encrypt encrypts the given secret string with RSA-OAEP
// using the AppKey, SHA256 hash function and specified label
//
// Returns the base64 encoded cipher text
func EncryptOAEP(secret string, label string) (string, error) {
rng := rand.Reader
cipherText, err := rsa.EncryptOAEP(sha256.New(), rng, AppPublicKey, []byte(secret), []byte(label))
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(cipherText), nil
}
// Decrypt decrypts the given base64 encoded RSA-OAEP cipher text
// using the AppKey, SHA256 hash function
//
// # Returns the plain text string
//
// The label parameter must match the value given when encrypting
func DecryptOAEP(cipher string, label string) (string, error) {
cipherText, err := base64.StdEncoding.DecodeString(cipher)
if err != nil {
return "", err
}
secret, err := rsa.DecryptOAEP(sha256.New(), nil, AppPrivateKey, []byte(cipherText), []byte(label))
if err != nil {
return "", err
}
return string(secret), nil
}