-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathsecurity_upload.nim
68 lines (53 loc) · 2.28 KB
/
security_upload.nim
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
import nimcrypto, zip/zipfiles, std/[ sequtils, strutils, strformat, os, osproc ]
import ../../common/[ config, trace_index, lang ]
proc generateSecurePassword*(): string =
var key: array[32, byte]
discard randomBytes(key)
result = key.mapIt(it.toHex(2)).join("")
return result
proc pkcs7Pad*(data: seq[byte], blockSize: int): seq[byte] =
let padLen = blockSize - (data.len mod blockSize)
result = data & repeat(cast[byte](padLen), padLen)
proc pkcs7Unpad*(data: seq[byte]): seq[byte] =
if data.len == 0:
raise newException(ValueError, "Data is empty, cannot unpad")
let padLen = int64(data[^1]) # Convert last byte to int64 safely
if padLen <= 0 or padLen > data.len:
raise newException(ValueError, "Invalid padding")
result = data[0 ..< data.len - padLen]
func toBytes*(s: string): seq[byte] =
## Convert a string to the corresponding byte sequence - since strings in
## nim essentially are byte sequences without any particular encoding, this
## simply copies the bytes without a null terminator
when nimvm:
var r = newSeq[byte](s.len)
for i, c in s:
r[i] = cast[byte](c)
r
else:
@(s.toOpenArrayByte(0, s.high))
proc encryptZip(zipFile, password: string) =
var iv: seq[byte] = password.toBytes()[0..15]
var aes: CBC[aes256]
aes.init(password.toOpenArrayByte(0, len(password) - 1), iv)
var zipData = readFile(zipFile).toBytes()
var paddedData = pkcs7Pad(zipData, 16)
var encrypted = newSeq[byte](paddedData.len)
aes.encrypt(paddedData, encrypted.toOpenArray(0, len(encrypted) - 1))
writeFile(zipFile & ".enc", encrypted)
proc zipFileWithEncryption*(inputFile: string, outputZip: string, password: string) =
var zip: ZipArchive
if not zip.open(outputZip, fmWrite):
raise newException(IOError, "Failed to create zip file: " & outputZip)
for file in walkDirRec(inputFile):
let relPath = file.relativePath(inputFile)
zip.addFile(relPath, file)
zip.close()
encryptZip(outputZip, password)
removeFile(outputZip)
proc uploadEncyptedZip*(file: string): (string, int) =
# TODO: Plug in http client instead of curl
let config = loadConfig(folder=getCurrentDir(), inTest=false)
let cmd = &"curl -s -X POST -F \"file=@{file}.enc\" {config.webApiRoot}/upload"
let (output, exitCode) = execCmdEx(cmd)
(output, exitCode)