Skip to content

Commit 7c75a2e

Browse files
authored
Hex+aes (#71)
1 parent 1aed397 commit 7c75a2e

File tree

9 files changed

+218
-37
lines changed

9 files changed

+218
-37
lines changed

crypto/README.md

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,22 @@
33
## Functions
44
- `md5(string)` - return md5 checksum from string.
55
- `sha256(string)` - return sha256 checksum from string.
6-
- `aes_encrypt(string, string, string, string)` - return AES encrypted hex-encoded ciphertext
7-
- `aes_decrypt(string, string, string, string)` - return AES decrypted hex-encoded plain text
6+
- `aes_encrypt(string, string, string, string)` - return AES encrypted binary ciphertext
7+
- `aes_decrypt(string, string, string, string)` - return AES decrypted binary text
8+
- `aes_encrypt_hex(string, string, string, string)` - return AES encrypted hex-encoded ciphertext
9+
- `aes_decrypt_hex(string, string, string, string)` - return AES decrypted hex-encoded plain text
810

9-
AES support 3 modes: GCM, CBC, and CTR - first parameter is mode, second is hex-encoded key, third is hex-encoded initialization vector or nonce - depending on the mode, and forth is hex-encoded plain text or ciphertext.
11+
AES support 3 modes: GCM, CBC, and CTR - first parameter is mode, second is hex-encoded key, third is hex-encoded
12+
initialization vector or nonce - depending on the mode, and forth is hex-encoded plain text or ciphertext.
13+
14+
Since lua strings are binary safe, you can use any binary data as input and output and, for your convenience, the
15+
library also provides hex-encoded versions of the encrypt and decrypt functions. The first argument (the mode string)
16+
can be one of the following: "GCM", "CBC", or "CTR" (case-insensitive) and is not hex-encoded for the hex variants.
1017

1118
## Examples
1219

1320
```lua
14-
local crypto = require("crypto")
21+
local crypto = require 'crypto'
1522

1623
-- md5
1724
if not(crypto.md5("1\n") == "b026324c6904b2a9cb4b88d6d61c81d1") then
@@ -23,18 +30,46 @@ if not(crypto.sha256("1\n") == "4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9
2330
error("sha256")
2431
end
2532

26-
--- aes encrypt in GCM mode
27-
s, err = crypto.aes_encrypt(1, "86e15cbc1cbf510d8f2e51d4b63a2144", "b6b86d581a991a652158bd10", "48656c6c6f20776f726c64")
33+
--- aes encrypt in GCM mode with hex-encoded data
34+
s, err = crypto.aes_encrypt_hex(crypto.GCM, "86e15cbc1cbf510d8f2e51d4b63a2144", "b6b86d581a991a652158bd10", "48656c6c6f20776f726c64")
35+
assert(not err, err)
2836
if not(s == "7ec4e38508a26abf7b46e8dc90a7299d5144bcf045e460c3ef6b3e") then
2937
error("encrypt AES")
3038
end
31-
assert(not err, err)
3239

33-
--- aes decrypt in GCM mode
34-
s, err = crypto.aes_decrypt(1, "86e15cbc1cbf510d8f2e51d4b63a2144", "b6b86d581a991a652158bd10", "7ec4e38508a26abf7b46e8dc90a7299d5144bcf045e460c3ef6b3e")
40+
--- aes decrypt in GCM mode with hex-encoded data
41+
s, err = crypto.aes_decrypt_hex(crypto.GCM, "86e15cbc1cbf510d8f2e51d4b63a2144", "b6b86d581a991a652158bd10", "7ec4e38508a26abf7b46e8dc90a7299d5144bcf045e460c3ef6b3e")
42+
assert(not err, err)
3543
if not(s == "48656c6c6f20776f726c64") then
36-
error("decrypt AES)
44+
error("decrypt AES")
45+
end
46+
47+
--- Binary examples setup of binary strings equivalent to the hex-encoded strings above:
48+
local hex = require 'hex'
49+
local key, iv, plaintext, encrypted, err
50+
key, err = hex.decode_string('86e15cbc1cbf510d8f2e51d4b63a2144')
51+
assert(not err, err)
52+
iv, err = hex.decode_string('b6b86d581a991a652158bd10')
53+
assert(not err, err)
54+
plaintext, err = hex.decode_string('48656c6c6f20776f726c64')
55+
assert(not err, err)
56+
s, err = crypto.aes_encrypt(crypto.GCM, key, iv, plaintext)
57+
assert(not err, err)
58+
encrypted, err = hex.decode_string("7ec4e38508a26abf7b46e8dc90a7299d5144bcf045e460c3ef6b3e")
59+
assert(not err, err)
60+
61+
--- aes encrypt binary in GCM mode
62+
s, err = crypto.aes_encrypt(crypto.GCM, key, iv, plaintext)
63+
assert(not err, err)
64+
if not(s == encrypted) then
65+
error("encrypt AES")
3766
end
67+
68+
--- aes decrypt in GCM mode
69+
s, err = crypto.aes_decrypt(crypto.GCM, key, iv, encrypted)
3870
assert(not err, err)
71+
if not(s == plaintext) then
72+
error("decrypt AES")
73+
end
3974

4075
```

crypto/api.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,26 @@ func SHA256(L *lua.LState) int {
2828

2929
// AESEncrypt implements AES encryption in Lua.
3030
func AESEncrypt(l *lua.LState) int {
31+
modeStr := l.CheckString(1)
32+
m, err := parseString(modeStr)
33+
if err != nil {
34+
l.ArgError(1, err.Error())
35+
}
36+
key := []byte(l.CheckString(2))
37+
iv := []byte(l.CheckString(3))
38+
data := []byte(l.CheckString(4))
39+
enc, err := encryptAES(m, key, iv, data)
40+
if err != nil {
41+
l.Push(lua.LNil)
42+
l.Push(lua.LString(fmt.Sprintf("failed to encrypt: %v", err)))
43+
return 2
44+
}
45+
l.Push(lua.LString(enc))
46+
return 1
47+
}
48+
49+
// AESEncryptHex implements AES encryption in Lua.
50+
func AESEncryptHex(l *lua.LState) int {
3151
m, key, iv, data, err := decodeParams(l)
3252
if err != nil {
3353
l.Push(lua.LNil)
@@ -47,6 +67,26 @@ func AESEncrypt(l *lua.LState) int {
4767

4868
// AESDecrypt implement AES decryption in Lua.
4969
func AESDecrypt(l *lua.LState) int {
70+
modeStr := l.CheckString(1)
71+
m, err := parseString(modeStr)
72+
if err != nil {
73+
l.ArgError(1, err.Error())
74+
}
75+
key := []byte(l.CheckString(2))
76+
iv := []byte(l.CheckString(3))
77+
data := []byte(l.CheckString(4))
78+
dec, err := decryptAES(m, key, iv, data)
79+
if err != nil {
80+
l.Push(lua.LNil)
81+
l.Push(lua.LString(fmt.Sprintf("failed to decrypt: %v", err)))
82+
return 2
83+
}
84+
l.Push(lua.LString(dec))
85+
return 1
86+
}
87+
88+
// AESDecryptHex implement AES decryption in Lua.
89+
func AESDecryptHex(l *lua.LState) int {
5090
m, key, iv, data, err := decodeParams(l)
5191
if err != nil {
5292
l.Push(lua.LNil)

crypto/api_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,18 @@ import (
44
"testing"
55

66
"github.com/stretchr/testify/assert"
7+
"github.com/vadv/gopher-lua-libs/filepath"
8+
"github.com/vadv/gopher-lua-libs/hex"
9+
"github.com/vadv/gopher-lua-libs/ioutil"
710
"github.com/vadv/gopher-lua-libs/tests"
811
)
912

1013
func TestApi(t *testing.T) {
11-
preload := tests.SeveralPreloadFuncs(Preload)
14+
preload := tests.SeveralPreloadFuncs(
15+
Preload,
16+
filepath.Preload,
17+
hex.Preload,
18+
ioutil.Preload,
19+
)
1220
assert.NotZero(t, tests.RunLuaTestFile(t, preload, "./test/test_api.lua"))
1321
}

crypto/loader.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,20 @@ func Preload(L *lua.LState) {
1313
// Loader is the module loader function.
1414
func Loader(L *lua.LState) int {
1515
t := L.NewTable()
16+
// Load the constants
17+
for name := range modeNames {
18+
t.RawSetString(name, lua.LString(name))
19+
}
1620
L.SetFuncs(t, api)
1721
L.Push(t)
1822
return 1
1923
}
2024

2125
var api = map[string]lua.LGFunction{
22-
"md5": MD5,
23-
"sha256": SHA256,
24-
"aes_encrypt": AESEncrypt,
25-
"aes_decrypt": AESDecrypt,
26+
"md5": MD5,
27+
"sha256": SHA256,
28+
"aes_encrypt_hex": AESEncryptHex,
29+
"aes_decrypt_hex": AESDecryptHex,
30+
"aes_encrypt": AESEncrypt,
31+
"aes_decrypt": AESDecrypt,
2632
}

crypto/test/data/1.data.bin

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello world

crypto/test/data/1.expected.bin

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
�4� �����

crypto/test/data/1.init.bin

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
�¿: ������

crypto/test/data/1.key.bin

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
��\��Q�.QԶ:!D

0 commit comments

Comments
 (0)