/
crypto.go
151 lines (128 loc) · 4.07 KB
/
crypto.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
// Copyright (c) Jeevanandam M. (https://github.com/jeevatkm)
// Source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.
package acrypto
import (
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/base64"
"errors"
"hash"
"strings"
"aahframe.work/essentials"
)
var (
// ErrUnableToDecrypt returned for decrypt errors.
ErrUnableToDecrypt = errors.New("security/crypto: unable to decrypt")
)
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
// Package Encrypt/Decrypt methods
//___________________________________
// AESEncryptString is convenient method to do AES encryption.
//
// The key argument should be the AES key, either 16, 24, or 32 bytes
// to select AES-128, AES-192, or AES-256.
func AESEncryptString(key, text string) (string, error) {
ciperBlock, err := aes.NewCipher([]byte(key))
if err != nil {
return "", err
}
encrypted := AESEncrypt(ciperBlock, []byte(text))
return base64.URLEncoding.EncodeToString(encrypted), nil
}
// AESDecryptString is convenient method to do AES decryption.
// It decrypts the encrypted text with given key.
func AESDecryptString(key, encryptedText string) (string, error) {
ciperBlock, err := aes.NewCipher([]byte(key))
if err != nil {
return "", err
}
bytes, err := base64.URLEncoding.DecodeString(encryptedText)
if err != nil {
return "", err
}
textBytes, err := AESDecrypt(ciperBlock, bytes)
if err != nil {
return "", err
}
return string(textBytes), nil
}
// AESEncrypt method encrypts a given value with given key block in CTR mode.
func AESEncrypt(block cipher.Block, value []byte) []byte {
iv := ess.GenerateSecureRandomKey(block.BlockSize())
// encrypt it
stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(value, value)
// iv + encryptedtext
return append(iv, value...)
}
// AESDecrypt method decrypts a given value with the given key block in CTR mode.
func AESDecrypt(block cipher.Block, value []byte) ([]byte, error) {
size := block.BlockSize()
if len(value) > size {
// split iv and encryptedtext
iv := value[:size]
value = value[size:]
// decrypt it
stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(value, value)
return value, nil
}
return nil, ErrUnableToDecrypt
}
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
// Package Sign/Verify methods
//___________________________________
// SignString method signs the given text using provided key with HMAC SHA.
//
// Supported SHA's are SHA-1, SHA-224, SHA-256, SHA-384, SHA-512.
func SignString(key, text, sha string) string {
return base64.URLEncoding.EncodeToString(Sign([]byte(key), []byte(text), sha))
}
// VerifyString method verifies the signed text and text using provide key with
// HMAC SHA. Returns true if sign is valid otherwise false.
//
// Supported SHA's are SHA-1, SHA-224, SHA-256, SHA-384, SHA-512.
func VerifyString(key, text, signedText, sha string) (bool, error) {
macText, err := base64.URLEncoding.DecodeString(signedText)
if err != nil {
return false, err
}
return Verify([]byte(key), []byte(text), macText, sha), nil
}
// Sign method signs a given value using HMAC and given SHA name.
func Sign(key, value []byte, sha string) []byte {
mac := hmac.New(hashFunc(sha), key)
defer mac.Reset()
_, _ = mac.Write(value)
return mac.Sum(nil)
}
// Verify method verifies given key, value and mac is valid. If valid
// it returns true otherwise false.
func Verify(key, value, mac []byte, sha string) bool {
otherMac := Sign(key, value, sha)
return hmac.Equal(mac, otherMac)
}
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
// Unexported methods
//___________________________________
func hashFunc(alg string) func() hash.Hash {
switch strings.ToLower(alg) {
case "sha-512":
return sha512.New
case "sha-384":
return sha512.New384
case "sha-256":
return sha256.New
case "sha-224":
return sha256.New224
case "sha-1":
return sha1.New
default:
return nil
}
}