Skip to content
This repository was archived by the owner on Aug 17, 2024. It is now read-only.

Commit f3bab9c

Browse files
author
Federico Ceratto
committed
Add XSalsa20 cypher
1 parent 0e2de3f commit f3bab9c

File tree

2 files changed

+116
-2
lines changed

2 files changed

+116
-2
lines changed

libsodium/sodium.nim

+63-2
Original file line numberDiff line numberDiff line change
@@ -841,8 +841,8 @@ proc crypto_stream_salsa20(
841841

842842
proc crypto_stream_salsa20*(nonce, key: string, length: int): string =
843843
## Salsa20 stream cypher.
844-
## `nonce` requires lenght of crypto_stream_salsa20_NONCEBYTES
845-
## `key` requires crypto_stream_salsa20_KEYBYTES
844+
## `nonce` requires lenght of crypto_stream_salsa20_NONCEBYTES (64 bits)
845+
## `key` requires crypto_stream_salsa20_KEYBYTES (256 bits)
846846
## Returns `lenght` bytes.
847847
doAssert nonce.len == crypto_stream_salsa20_NONCEBYTES()
848848
doAssert key.len == crypto_stream_salsa20_KEYBYTES()
@@ -913,3 +913,64 @@ proc crypto_stream_salsa20_keygen*(): string =
913913
result = newString crypto_stream_salsa20_KEYBYTES()
914914
let o = cpt result
915915
crypto_stream_salsa20_keygen(o)
916+
917+
918+
# XSalsa20
919+
920+
proc crypto_stream(
921+
c: ptr cuchar,
922+
clen: csize,
923+
n: ptr cuchar,
924+
k: ptr cuchar
925+
):cint {.sodium_import.}
926+
927+
proc crypto_stream*(nonce, key: string, length: int): string =
928+
## XSalsa20 stream cypher.
929+
## `nonce` requires lenght of crypto_stream_xsalsa20_NONCEBYTES (192 bits)
930+
## `key` requires crypto_stream_xsalsa20_KEYBYTES (256 bits)
931+
## Returns `lenght` bytes.
932+
doAssert nonce.len == crypto_stream_xsalsa20_NONCEBYTES()
933+
doAssert key.len == crypto_stream_xsalsa20_KEYBYTES()
934+
result = newString length
935+
let
936+
c = cpt result
937+
clen = cpsize result
938+
n = cpt nonce
939+
k = cpt key
940+
rc = crypto_stream(c, clen, n, k)
941+
check_rc rc
942+
943+
944+
proc crypto_stream_xor(
945+
c: ptr cuchar,
946+
m: ptr cuchar,
947+
mlen: csize,
948+
n: ptr cuchar,
949+
k: ptr cuchar
950+
):cint {.sodium_import.}
951+
952+
proc crypto_stream_xor*(nonce, key, msg: string): string =
953+
## encrypts `msg` using XSalsa20.
954+
## `nonce` requires lenght of crypto_stream_xsalsa20_NONCEBYTES
955+
## `key` requires crypto_stream_xsalsa20_KEYBYTES
956+
result = newString msg.len
957+
let
958+
c = cpt result
959+
m = cpt msg
960+
mlen = cpsize msg
961+
n = cpt nonce
962+
k = cpt key
963+
rc = crypto_stream_xor(c, m, mlen, n, k)
964+
check_rc rc
965+
966+
967+
proc crypto_stream_keygen(
968+
k: ptr cuchar,
969+
) {.sodium_import.}
970+
971+
proc crypto_stream_keygen*(): string =
972+
## Returns `crypto_stream_xsalsa20_KEYBYTES` random bytes.
973+
## To be used with `crypto_stream` or `crypto_stream_xor`
974+
result = newString crypto_stream_salsa20_KEYBYTES()
975+
let o = cpt result
976+
crypto_stream_keygen(o)

test_sodium.nim

+53
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ suite "HMAC":
291291

292292
suite "stream ciphers":
293293

294+
test "Salsa20 sizes":
295+
check crypto_stream_salsa20_NONCEBYTES() * 8 == 64
296+
check crypto_stream_salsa20_KEYBYTES() * 8 == 256
297+
294298
test "Salsa20 keygen":
295299
let key = crypto_stream_salsa20_keygen()
296300
check crypto_auth_KEYBYTES() == 32
@@ -345,3 +349,52 @@ suite "stream ciphers":
345349

346350
let decrypted = crypto_stream_salsa20_xor_ic(nonce, key, c, 0)
347351
check decrypted == "hello there"
352+
353+
# XSalsa20
354+
355+
test "XSalsa20 sizes":
356+
check crypto_stream_xsalsa20_NONCEBYTES() * 8 == 192
357+
check crypto_stream_xsalsa20_KEYBYTES() * 8 == 256
358+
359+
test "XSalsa20 keygen":
360+
let key = crypto_stream_keygen()
361+
check crypto_auth_KEYBYTES() == 32
362+
check key.len == crypto_auth_KEYBYTES()
363+
364+
test "XSalsa20 stream":
365+
expect AssertionError:
366+
let nonce = repeat("n", crypto_stream_xsalsa20_NONCEBYTES())
367+
discard crypto_stream(nonce, "", 1024)
368+
369+
expect AssertionError:
370+
let key = crypto_stream_keygen()
371+
discard crypto_stream("", key, 1024)
372+
373+
let
374+
key = repeat("k", crypto_stream_xsalsa20_KEYBYTES())
375+
nonce = repeat("n", crypto_stream_xsalsa20_NONCEBYTES())
376+
c = crypto_stream(nonce, key, 64)
377+
check c.bin2hex() == "91172bd584998fa76d97a543eccf9eafdde4107708b45dda53ad660ebfc44656c8c850d59229d2a15e54fb6a1119be624e1880c0916eb6e08b2557e1d03db9da"
378+
379+
test "XSalsa20 stream xor":
380+
const
381+
key = "this is 32-byte key for xsalsa20"
382+
nonce = "24-byte nonce for xsalsa"
383+
msg = "Hello world!"
384+
let
385+
c = crypto_stream_xor(nonce, key, msg)
386+
check c.bin2hex() == "002d4513843fc240c401e541"
387+
388+
let decrypted = crypto_stream_xor(nonce, key, c)
389+
check decrypted == msg
390+
391+
test "XSalsa20 stream xor":
392+
let
393+
key = repeat("k", crypto_stream_xsalsa20_KEYBYTES())
394+
nonce = repeat("n", crypto_stream_xsalsa20_NONCEBYTES())
395+
msg = "hello there"
396+
c = crypto_stream_xor(nonce, key, msg)
397+
check c.bin2hex() == "f97247b9ebb9fbcf08e5c0"
398+
399+
let decrypted = crypto_stream_xor(nonce, key, c)
400+
check decrypted == "hello there"

0 commit comments

Comments
 (0)