mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 14:48:47 +00:00
Update tests\core\crypto
This commit is contained in:
+3
-3
@@ -42,15 +42,15 @@ compress_test:
|
|||||||
container_test:
|
container_test:
|
||||||
$(ODIN) test container $(COMMON) -define:test_progress_width=4 -out:test_core_container
|
$(ODIN) test container $(COMMON) -define:test_progress_width=4 -out:test_core_container
|
||||||
|
|
||||||
|
crypto_test:
|
||||||
|
$(ODIN) test crypto $(COMMON) -define:test_progress_width=18 -o:speed -out:test_crypto
|
||||||
|
|
||||||
strings_test:
|
strings_test:
|
||||||
$(ODIN) run strings $(COMMON) -out:test_core_strings
|
$(ODIN) run strings $(COMMON) -out:test_core_strings
|
||||||
|
|
||||||
hash_test:
|
hash_test:
|
||||||
$(ODIN) run hash $(COMMON) -o:speed -out:test_hash
|
$(ODIN) run hash $(COMMON) -o:speed -out:test_hash
|
||||||
|
|
||||||
crypto_test:
|
|
||||||
$(ODIN) run crypto $(COMMON) $(COLLECTION) -o:speed -out:test_crypto
|
|
||||||
|
|
||||||
noise_test:
|
noise_test:
|
||||||
$(ODIN) run math/noise $(COMMON) -out:test_noise
|
$(ODIN) run math/noise $(COMMON) -out:test_noise
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ echo ---
|
|||||||
echo ---
|
echo ---
|
||||||
echo Running core:crypto tests
|
echo Running core:crypto tests
|
||||||
echo ---
|
echo ---
|
||||||
%PATH_TO_ODIN% run crypto %COMMON% %COLLECTION% -out:test_crypto.exe || exit /b
|
%PATH_TO_ODIN% test crypto %COMMON% define:test_progress_width=18 -o:speed -out:test_crypto.exe || exit /b
|
||||||
|
|
||||||
echo ---
|
echo ---
|
||||||
echo Running core:encoding tests
|
echo Running core:encoding tests
|
||||||
|
|||||||
@@ -13,41 +13,20 @@ package test_core_crypto
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import "core:encoding/hex"
|
import "core:encoding/hex"
|
||||||
import "core:fmt"
|
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
|
import "base:runtime"
|
||||||
|
import "core:log"
|
||||||
|
|
||||||
import "core:crypto"
|
import "core:crypto"
|
||||||
import "core:crypto/chacha20"
|
import "core:crypto/chacha20"
|
||||||
import "core:crypto/chacha20poly1305"
|
import "core:crypto/chacha20poly1305"
|
||||||
|
|
||||||
import tc "tests:common"
|
|
||||||
|
|
||||||
main :: proc() {
|
|
||||||
t := testing.T{}
|
|
||||||
|
|
||||||
test_rand_bytes(&t)
|
|
||||||
|
|
||||||
test_hash(&t)
|
|
||||||
test_mac(&t)
|
|
||||||
test_kdf(&t) // After hash/mac tests because those should pass first.
|
|
||||||
test_ecc25519(&t)
|
|
||||||
|
|
||||||
test_aes(&t)
|
|
||||||
test_chacha20(&t)
|
|
||||||
test_chacha20poly1305(&t)
|
|
||||||
test_sha3_variants(&t)
|
|
||||||
|
|
||||||
bench_crypto(&t)
|
|
||||||
|
|
||||||
tc.report(&t)
|
|
||||||
}
|
|
||||||
|
|
||||||
_PLAINTEXT_SUNSCREEN_STR := "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."
|
_PLAINTEXT_SUNSCREEN_STR := "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_chacha20 :: proc(t: ^testing.T) {
|
test_chacha20 :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing (X)ChaCha20")
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
// Test cases taken from RFC 8439, and draft-irtf-cfrg-xchacha-03
|
// Test cases taken from RFC 8439, and draft-irtf-cfrg-xchacha-03
|
||||||
plaintext := transmute([]byte)(_PLAINTEXT_SUNSCREEN_STR)
|
plaintext := transmute([]byte)(_PLAINTEXT_SUNSCREEN_STR)
|
||||||
@@ -90,14 +69,12 @@ test_chacha20 :: proc(t: ^testing.T) {
|
|||||||
chacha20.xor_bytes(&ctx, derived_ciphertext[:], plaintext[:])
|
chacha20.xor_bytes(&ctx, derived_ciphertext[:], plaintext[:])
|
||||||
|
|
||||||
derived_ciphertext_str := string(hex.encode(derived_ciphertext[:], context.temp_allocator))
|
derived_ciphertext_str := string(hex.encode(derived_ciphertext[:], context.temp_allocator))
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
derived_ciphertext_str == ciphertext_str,
|
derived_ciphertext_str == ciphertext_str,
|
||||||
fmt.tprintf(
|
"Expected %s for xor_bytes(plaintext_str), but got %s instead",
|
||||||
"Expected %s for xor_bytes(plaintext_str), but got %s instead",
|
ciphertext_str,
|
||||||
ciphertext_str,
|
derived_ciphertext_str,
|
||||||
derived_ciphertext_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
xkey := [chacha20.KEY_SIZE]byte {
|
xkey := [chacha20.KEY_SIZE]byte {
|
||||||
@@ -137,21 +114,17 @@ test_chacha20 :: proc(t: ^testing.T) {
|
|||||||
chacha20.xor_bytes(&ctx, derived_ciphertext[:], plaintext[:])
|
chacha20.xor_bytes(&ctx, derived_ciphertext[:], plaintext[:])
|
||||||
|
|
||||||
derived_ciphertext_str = string(hex.encode(derived_ciphertext[:], context.temp_allocator))
|
derived_ciphertext_str = string(hex.encode(derived_ciphertext[:], context.temp_allocator))
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
derived_ciphertext_str == xciphertext_str,
|
derived_ciphertext_str == xciphertext_str,
|
||||||
fmt.tprintf(
|
"Expected %s for xor_bytes(plaintext_str), but got %s instead",
|
||||||
"Expected %s for xor_bytes(plaintext_str), but got %s instead",
|
xciphertext_str,
|
||||||
xciphertext_str,
|
derived_ciphertext_str,
|
||||||
derived_ciphertext_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_chacha20poly1305 :: proc(t: ^testing.T) {
|
test_chacha20poly1305 :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing chacha20poly1205")
|
|
||||||
|
|
||||||
plaintext := transmute([]byte)(_PLAINTEXT_SUNSCREEN_STR)
|
plaintext := transmute([]byte)(_PLAINTEXT_SUNSCREEN_STR)
|
||||||
|
|
||||||
aad := [12]byte {
|
aad := [12]byte {
|
||||||
@@ -209,25 +182,21 @@ test_chacha20poly1305 :: proc(t: ^testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
derived_ciphertext_str := string(hex.encode(derived_ciphertext[:], context.temp_allocator))
|
derived_ciphertext_str := string(hex.encode(derived_ciphertext[:], context.temp_allocator))
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
derived_ciphertext_str == ciphertext_str,
|
derived_ciphertext_str == ciphertext_str,
|
||||||
fmt.tprintf(
|
"Expected ciphertext %s for encrypt(aad, plaintext), but got %s instead",
|
||||||
"Expected ciphertext %s for encrypt(aad, plaintext), but got %s instead",
|
ciphertext_str,
|
||||||
ciphertext_str,
|
derived_ciphertext_str,
|
||||||
derived_ciphertext_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
derived_tag_str := string(hex.encode(derived_tag[:], context.temp_allocator))
|
derived_tag_str := string(hex.encode(derived_tag[:], context.temp_allocator))
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
derived_tag_str == tag_str,
|
derived_tag_str == tag_str,
|
||||||
fmt.tprintf(
|
"Expected tag %s for encrypt(aad, plaintext), but got %s instead",
|
||||||
"Expected tag %s for encrypt(aad, plaintext), but got %s instead",
|
tag_str,
|
||||||
tag_str,
|
derived_tag_str,
|
||||||
derived_tag_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
derived_plaintext: [114]byte
|
derived_plaintext: [114]byte
|
||||||
@@ -240,15 +209,13 @@ test_chacha20poly1305 :: proc(t: ^testing.T) {
|
|||||||
ciphertext[:],
|
ciphertext[:],
|
||||||
)
|
)
|
||||||
derived_plaintext_str := string(derived_plaintext[:])
|
derived_plaintext_str := string(derived_plaintext[:])
|
||||||
tc.expect(t, ok, "Expected true for decrypt(tag, aad, ciphertext)")
|
testing.expect(t, ok, "Expected true for decrypt(tag, aad, ciphertext)")
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
derived_plaintext_str == _PLAINTEXT_SUNSCREEN_STR,
|
derived_plaintext_str == _PLAINTEXT_SUNSCREEN_STR,
|
||||||
fmt.tprintf(
|
"Expected plaintext %s for decrypt(tag, aad, ciphertext), but got %s instead",
|
||||||
"Expected plaintext %s for decrypt(tag, aad, ciphertext), but got %s instead",
|
_PLAINTEXT_SUNSCREEN_STR,
|
||||||
_PLAINTEXT_SUNSCREEN_STR,
|
derived_plaintext_str,
|
||||||
derived_plaintext_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
derived_ciphertext[0] ~= 0xa5
|
derived_ciphertext[0] ~= 0xa5
|
||||||
@@ -260,7 +227,7 @@ test_chacha20poly1305 :: proc(t: ^testing.T) {
|
|||||||
aad[:],
|
aad[:],
|
||||||
derived_ciphertext[:],
|
derived_ciphertext[:],
|
||||||
)
|
)
|
||||||
tc.expect(t, !ok, "Expected false for decrypt(tag, aad, corrupted_ciphertext)")
|
testing.expect(t, !ok, "Expected false for decrypt(tag, aad, corrupted_ciphertext)")
|
||||||
|
|
||||||
aad[0] ~= 0xa5
|
aad[0] ~= 0xa5
|
||||||
ok = chacha20poly1305.decrypt(
|
ok = chacha20poly1305.decrypt(
|
||||||
@@ -271,15 +238,13 @@ test_chacha20poly1305 :: proc(t: ^testing.T) {
|
|||||||
aad[:],
|
aad[:],
|
||||||
ciphertext[:],
|
ciphertext[:],
|
||||||
)
|
)
|
||||||
tc.expect(t, !ok, "Expected false for decrypt(tag, corrupted_aad, ciphertext)")
|
testing.expect(t, !ok, "Expected false for decrypt(tag, corrupted_aad, ciphertext)")
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_rand_bytes :: proc(t: ^testing.T) {
|
test_rand_bytes :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing rand_bytes")
|
|
||||||
|
|
||||||
if !crypto.HAS_RAND_BYTES {
|
if !crypto.HAS_RAND_BYTES {
|
||||||
tc.log(t, "rand_bytes not supported - skipping")
|
log.info("rand_bytes not supported - skipping")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,10 +272,5 @@ test_rand_bytes :: proc(t: ^testing.T) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
testing.expect(t, seems_ok, "Expected to randomize the head and tail of the buffer within a handful of attempts")
|
||||||
tc.expect(
|
|
||||||
t,
|
|
||||||
seems_ok,
|
|
||||||
"Expected to randomize the head and tail of the buffer within a handful of attempts",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,17 @@ package test_core_crypto
|
|||||||
|
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
import "core:encoding/hex"
|
import "core:encoding/hex"
|
||||||
import "core:fmt"
|
import "core:log"
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
|
|
||||||
import "core:crypto/aes"
|
import "core:crypto/aes"
|
||||||
import "core:crypto/sha2"
|
import "core:crypto/sha2"
|
||||||
|
|
||||||
import tc "tests:common"
|
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_aes :: proc(t: ^testing.T) {
|
test_aes :: proc(t: ^testing.T) {
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
tc.log(t, "Testing AES")
|
log.info("Testing AES")
|
||||||
|
|
||||||
impls := make([dynamic]aes.Implementation, 0, 2)
|
impls := make([dynamic]aes.Implementation, 0, 2)
|
||||||
append(&impls, aes.Implementation.Portable)
|
append(&impls, aes.Implementation.Portable)
|
||||||
@@ -29,9 +27,8 @@ test_aes :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_aes_ecb :: proc(t: ^testing.T, impl: aes.Implementation) {
|
test_aes_ecb :: proc(t: ^testing.T, impl: aes.Implementation) {
|
||||||
tc.log(t, fmt.tprintf("Testing AES-ECB/%v", impl))
|
log.infof("Testing AES-ECB/%v", impl)
|
||||||
|
|
||||||
test_vectors := []struct {
|
test_vectors := []struct {
|
||||||
key: string,
|
key: string,
|
||||||
@@ -111,39 +108,34 @@ test_aes_ecb :: proc(t: ^testing.T, impl: aes.Implementation) {
|
|||||||
|
|
||||||
aes.encrypt_ecb(&ctx, dst[:], plaintext)
|
aes.encrypt_ecb(&ctx, dst[:], plaintext)
|
||||||
dst_str := string(hex.encode(dst[:], context.temp_allocator))
|
dst_str := string(hex.encode(dst[:], context.temp_allocator))
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
dst_str == v.ciphertext,
|
dst_str == v.ciphertext,
|
||||||
fmt.tprintf(
|
"AES-ECB/%v: Expected: %s for encrypt(%s, %s), but got %s instead",
|
||||||
"AES-ECB/%v: Expected: %s for encrypt(%s, %s), but got %s instead",
|
impl,
|
||||||
impl,
|
v.ciphertext,
|
||||||
v.ciphertext,
|
v.key,
|
||||||
v.key,
|
v.plaintext,
|
||||||
v.plaintext,
|
dst_str,
|
||||||
dst_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
aes.decrypt_ecb(&ctx, dst[:], ciphertext)
|
aes.decrypt_ecb(&ctx, dst[:], ciphertext)
|
||||||
dst_str = string(hex.encode(dst[:], context.temp_allocator))
|
dst_str = string(hex.encode(dst[:], context.temp_allocator))
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
dst_str == v.plaintext,
|
dst_str == v.plaintext,
|
||||||
fmt.tprintf(
|
"AES-ECB/%v: Expected: %s for decrypt(%s, %s), but got %s instead",
|
||||||
"AES-ECB/%v: Expected: %s for decrypt(%s, %s), but got %s instead",
|
impl,
|
||||||
impl,
|
v.plaintext,
|
||||||
v.plaintext,
|
v.key,
|
||||||
v.key,
|
v.ciphertext,
|
||||||
v.ciphertext,
|
dst_str,
|
||||||
dst_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_aes_ctr :: proc(t: ^testing.T, impl: aes.Implementation) {
|
test_aes_ctr :: proc(t: ^testing.T, impl: aes.Implementation) {
|
||||||
tc.log(t, fmt.tprintf("Testing AES-CTR/%v", impl))
|
log.infof("Testing AES-CTR/%v", impl)
|
||||||
|
|
||||||
test_vectors := []struct {
|
test_vectors := []struct {
|
||||||
key: string,
|
key: string,
|
||||||
@@ -185,18 +177,16 @@ test_aes_ctr :: proc(t: ^testing.T, impl: aes.Implementation) {
|
|||||||
aes.xor_bytes_ctr(&ctx, dst, plaintext)
|
aes.xor_bytes_ctr(&ctx, dst, plaintext)
|
||||||
|
|
||||||
dst_str := string(hex.encode(dst[:], context.temp_allocator))
|
dst_str := string(hex.encode(dst[:], context.temp_allocator))
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
dst_str == v.ciphertext,
|
dst_str == v.ciphertext,
|
||||||
fmt.tprintf(
|
"AES-CTR/%v: Expected: %s for encrypt(%s, %s, %s), but got %s instead",
|
||||||
"AES-CTR/%v: Expected: %s for encrypt(%s, %s, %s), but got %s instead",
|
impl,
|
||||||
impl,
|
v.ciphertext,
|
||||||
v.ciphertext,
|
v.key,
|
||||||
v.key,
|
v.iv,
|
||||||
v.iv,
|
v.plaintext,
|
||||||
v.plaintext,
|
dst_str,
|
||||||
dst_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,21 +214,18 @@ test_aes_ctr :: proc(t: ^testing.T, impl: aes.Implementation) {
|
|||||||
digest_str := string(hex.encode(digest[:], context.temp_allocator))
|
digest_str := string(hex.encode(digest[:], context.temp_allocator))
|
||||||
|
|
||||||
expected_digest_str := "d4445343afeb9d1237f95b10d00358aed4c1d7d57c9fe480cd0afb5e2ffd448c"
|
expected_digest_str := "d4445343afeb9d1237f95b10d00358aed4c1d7d57c9fe480cd0afb5e2ffd448c"
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
expected_digest_str == digest_str,
|
expected_digest_str == digest_str,
|
||||||
fmt.tprintf(
|
"AES-CTR/%v: Expected %s for keystream digest, but got %s instead",
|
||||||
"AES-CTR/%v: Expected %s for keystream digest, but got %s instead",
|
impl,
|
||||||
impl,
|
expected_digest_str,
|
||||||
expected_digest_str,
|
digest_str,
|
||||||
digest_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_aes_gcm :: proc(t: ^testing.T, impl: aes.Implementation) {
|
test_aes_gcm :: proc(t: ^testing.T, impl: aes.Implementation) {
|
||||||
tc.log(t, fmt.tprintf("Testing AES-GCM/%v", impl))
|
log.infof("Testing AES-GCM/%v", impl)
|
||||||
|
|
||||||
// NIST did a reorg of their site, so the source of the test vectors
|
// NIST did a reorg of their site, so the source of the test vectors
|
||||||
// is only available from an archive. The commented out tests are
|
// is only available from an archive. The commented out tests are
|
||||||
@@ -422,41 +409,37 @@ test_aes_gcm :: proc(t: ^testing.T, impl: aes.Implementation) {
|
|||||||
dst_str := string(hex.encode(dst[:], context.temp_allocator))
|
dst_str := string(hex.encode(dst[:], context.temp_allocator))
|
||||||
tag_str := string(hex.encode(tag_[:], context.temp_allocator))
|
tag_str := string(hex.encode(tag_[:], context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
dst_str == v.ciphertext && tag_str == v.tag,
|
dst_str == v.ciphertext && tag_str == v.tag,
|
||||||
fmt.tprintf(
|
"AES-GCM/%v: Expected: (%s, %s) for seal(%s, %s, %s, %s), but got (%s, %s) instead",
|
||||||
"AES-GCM/%v: Expected: (%s, %s) for seal(%s, %s, %s, %s), but got (%s, %s) instead",
|
impl,
|
||||||
impl,
|
v.ciphertext,
|
||||||
v.ciphertext,
|
v.tag,
|
||||||
v.tag,
|
v.key,
|
||||||
v.key,
|
v.iv,
|
||||||
v.iv,
|
v.aad,
|
||||||
v.aad,
|
v.plaintext,
|
||||||
v.plaintext,
|
dst_str,
|
||||||
dst_str,
|
tag_str,
|
||||||
tag_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ok := aes.open_gcm(&ctx, dst, iv, aad, ciphertext, tag)
|
ok := aes.open_gcm(&ctx, dst, iv, aad, ciphertext, tag)
|
||||||
dst_str = string(hex.encode(dst[:], context.temp_allocator))
|
dst_str = string(hex.encode(dst[:], context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
ok && dst_str == v.plaintext,
|
ok && dst_str == v.plaintext,
|
||||||
fmt.tprintf(
|
"AES-GCM/%v: Expected: (%s, true) for open(%s, %s, %s, %s, %s), but got (%s, %s) instead",
|
||||||
"AES-GCM/%v: Expected: (%s, true) for open(%s, %s, %s, %s, %s), but got (%s, %s) instead",
|
impl,
|
||||||
impl,
|
v.plaintext,
|
||||||
v.plaintext,
|
v.key,
|
||||||
v.key,
|
v.iv,
|
||||||
v.iv,
|
v.aad,
|
||||||
v.aad,
|
v.ciphertext,
|
||||||
v.ciphertext,
|
v.tag,
|
||||||
v.tag,
|
dst_str,
|
||||||
dst_str,
|
ok,
|
||||||
ok,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package test_core_crypto
|
package test_core_crypto
|
||||||
|
|
||||||
import "base:runtime"
|
|
||||||
import "core:encoding/hex"
|
import "core:encoding/hex"
|
||||||
import "core:fmt"
|
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
|
|
||||||
import field "core:crypto/_fiat/field_curve25519"
|
import field "core:crypto/_fiat/field_curve25519"
|
||||||
@@ -10,25 +8,8 @@ import "core:crypto/ed25519"
|
|||||||
import "core:crypto/ristretto255"
|
import "core:crypto/ristretto255"
|
||||||
import "core:crypto/x25519"
|
import "core:crypto/x25519"
|
||||||
|
|
||||||
import tc "tests:common"
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_ecc25519 :: proc(t: ^testing.T) {
|
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
||||||
|
|
||||||
tc.log(t, "Testing curve25519 ECC")
|
|
||||||
|
|
||||||
test_sqrt_ratio_m1(t)
|
|
||||||
test_ristretto255(t)
|
|
||||||
|
|
||||||
test_ed25519(t)
|
|
||||||
test_x25519(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_sqrt_ratio_m1 :: proc(t: ^testing.T) {
|
test_sqrt_ratio_m1 :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing sqrt_ratio_m1")
|
|
||||||
|
|
||||||
test_vectors := []struct {
|
test_vectors := []struct {
|
||||||
u: string,
|
u: string,
|
||||||
v: string,
|
v: string,
|
||||||
@@ -90,25 +71,21 @@ test_sqrt_ratio_m1 :: proc(t: ^testing.T) {
|
|||||||
field.fe_relax_cast(&vee),
|
field.fe_relax_cast(&vee),
|
||||||
)
|
)
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
(was_square == 1) == v.was_square && field.fe_equal_bytes(&r, r_) == 1,
|
(was_square == 1) == v.was_square && field.fe_equal_bytes(&r, r_) == 1,
|
||||||
fmt.tprintf(
|
"Expected (%v, %s) for SQRT_RATIO_M1(%s, %s), got %s",
|
||||||
"Expected (%v, %s) for SQRT_RATIO_M1(%s, %s), got %s",
|
v.was_square,
|
||||||
v.was_square,
|
v.r,
|
||||||
v.r,
|
v.u,
|
||||||
v.u,
|
v.v,
|
||||||
v.v,
|
fe_str(&r),
|
||||||
fe_str(&r),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_ristretto255 :: proc(t: ^testing.T) {
|
test_ristretto255 :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing ristretto255")
|
|
||||||
|
|
||||||
ge_gen: ristretto255.Group_Element
|
ge_gen: ristretto255.Group_Element
|
||||||
ristretto255.ge_generator(&ge_gen)
|
ristretto255.ge_generator(&ge_gen)
|
||||||
|
|
||||||
@@ -158,7 +135,7 @@ test_ristretto255 :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
ge: ristretto255.Group_Element
|
ge: ristretto255.Group_Element
|
||||||
ok := ristretto255.ge_set_bytes(&ge, b)
|
ok := ristretto255.ge_set_bytes(&ge, b)
|
||||||
tc.expect(t, !ok, fmt.tprintf("Expected false for %s", x))
|
testing.expectf(t, !ok, "Expected false for %s", x)
|
||||||
}
|
}
|
||||||
|
|
||||||
generator_multiples := []string {
|
generator_multiples := []string {
|
||||||
@@ -185,22 +162,20 @@ test_ristretto255 :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
ge := &ges[i]
|
ge := &ges[i]
|
||||||
ok := ristretto255.ge_set_bytes(ge, b)
|
ok := ristretto255.ge_set_bytes(ge, b)
|
||||||
tc.expect(t, ok, fmt.tprintf("Expected true for %s", x))
|
testing.expectf(t, ok, "Expected true for %s", x)
|
||||||
|
|
||||||
x_check := ge_str(ge)
|
x_check := ge_str(ge)
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
x == x_check,
|
x == x_check,
|
||||||
fmt.tprintf(
|
"Expected %s (round-trip) but got %s instead",
|
||||||
"Expected %s (round-trip) but got %s instead",
|
x,
|
||||||
x,
|
x_check,
|
||||||
x_check,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if i == 1 {
|
if i == 1 {
|
||||||
tc.expect(
|
testing.expect(
|
||||||
t,
|
t,
|
||||||
ristretto255.ge_equal(ge, &ge_gen) == 1,
|
ristretto255.ge_equal(ge, &ge_gen) == 1,
|
||||||
"Expected element 1 to be the generator",
|
"Expected element 1 to be the generator",
|
||||||
@@ -217,41 +192,35 @@ test_ristretto255 :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
ristretto255.ge_scalarmult_generator(&ge_check, &sc)
|
ristretto255.ge_scalarmult_generator(&ge_check, &sc)
|
||||||
x_check := ge_str(&ge_check)
|
x_check := ge_str(&ge_check)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
x_check == generator_multiples[i],
|
x_check == generator_multiples[i],
|
||||||
fmt.tprintf(
|
"Expected %s for G * %d (specialized), got %s",
|
||||||
"Expected %s for G * %d (specialized), got %s",
|
generator_multiples[i],
|
||||||
generator_multiples[i],
|
i,
|
||||||
i,
|
x_check,
|
||||||
x_check,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ristretto255.ge_scalarmult(&ge_check, &ges[1], &sc)
|
ristretto255.ge_scalarmult(&ge_check, &ges[1], &sc)
|
||||||
x_check = ge_str(&ge_check)
|
x_check = ge_str(&ge_check)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
x_check == generator_multiples[i],
|
x_check == generator_multiples[i],
|
||||||
fmt.tprintf(
|
"Expected %s for G * %d (generic), got %s (slow compare)",
|
||||||
"Expected %s for G * %d (generic), got %s (slow compare)",
|
generator_multiples[i],
|
||||||
generator_multiples[i],
|
i,
|
||||||
i,
|
x_check,
|
||||||
x_check,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ristretto255.ge_scalarmult_vartime(&ge_check, &ges[1], &sc)
|
ristretto255.ge_scalarmult_vartime(&ge_check, &ges[1], &sc)
|
||||||
x_check = ge_str(&ge_check)
|
x_check = ge_str(&ge_check)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
x_check == generator_multiples[i],
|
x_check == generator_multiples[i],
|
||||||
fmt.tprintf(
|
"Expected %s for G * %d (generic vartime), got %s (slow compare)",
|
||||||
"Expected %s for G * %d (generic vartime), got %s (slow compare)",
|
generator_multiples[i],
|
||||||
generator_multiples[i],
|
i,
|
||||||
i,
|
x_check,
|
||||||
x_check,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
switch i {
|
switch i {
|
||||||
@@ -261,28 +230,24 @@ test_ristretto255 :: proc(t: ^testing.T) {
|
|||||||
ristretto255.ge_add(&ge_check, ge_prev, &ge_gen)
|
ristretto255.ge_add(&ge_check, ge_prev, &ge_gen)
|
||||||
|
|
||||||
x_check = ge_str(&ge_check)
|
x_check = ge_str(&ge_check)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
x_check == generator_multiples[i],
|
x_check == generator_multiples[i],
|
||||||
fmt.tprintf(
|
"Expected %s for ges[%d] + ges[%d], got %s (slow compare)",
|
||||||
"Expected %s for ges[%d] + ges[%d], got %s (slow compare)",
|
generator_multiples[i],
|
||||||
generator_multiples[i],
|
i-1,
|
||||||
i-1,
|
1,
|
||||||
1,
|
x_check,
|
||||||
x_check,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
ristretto255.ge_equal(&ges[i], &ge_check) == 1,
|
ristretto255.ge_equal(&ges[i], &ge_check) == 1,
|
||||||
fmt.tprintf(
|
"Expected %s for ges[%d] + ges[%d], got %s (fast compare)",
|
||||||
"Expected %s for ges[%d] + ges[%d], got %s (fast compare)",
|
generator_multiples[i],
|
||||||
generator_multiples[i],
|
i-1,
|
||||||
i-1,
|
1,
|
||||||
1,
|
x_check,
|
||||||
x_check,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,22 +309,18 @@ test_ristretto255 :: proc(t: ^testing.T) {
|
|||||||
ristretto255.ge_set_wide_bytes(&ge, in_bytes)
|
ristretto255.ge_set_wide_bytes(&ge, in_bytes)
|
||||||
|
|
||||||
ge_check := ge_str(&ge)
|
ge_check := ge_str(&ge)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
ge_check == v.output,
|
ge_check == v.output,
|
||||||
fmt.tprintf(
|
"Expected %s for %s, got %s",
|
||||||
"Expected %s for %s, got %s",
|
v.output,
|
||||||
v.output,
|
ge_check,
|
||||||
ge_check,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_ed25519 :: proc(t: ^testing.T) {
|
test_ed25519 :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing ed25519")
|
|
||||||
|
|
||||||
test_vectors_rfc := []struct {
|
test_vectors_rfc := []struct {
|
||||||
priv_key: string,
|
priv_key: string,
|
||||||
pub_key: string,
|
pub_key: string,
|
||||||
@@ -401,87 +362,73 @@ test_ed25519 :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
priv_key: ed25519.Private_Key
|
priv_key: ed25519.Private_Key
|
||||||
ok := ed25519.private_key_set_bytes(&priv_key, priv_bytes)
|
ok := ed25519.private_key_set_bytes(&priv_key, priv_bytes)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
ok,
|
ok,
|
||||||
fmt.tprintf(
|
"Expected %s to be a valid private key",
|
||||||
"Expected %s to be a valid private key",
|
v.priv_key,
|
||||||
v.priv_key,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
key_bytes: [32]byte
|
key_bytes: [32]byte
|
||||||
ed25519.private_key_bytes(&priv_key, key_bytes[:])
|
ed25519.private_key_bytes(&priv_key, key_bytes[:])
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
ok,
|
ok,
|
||||||
fmt.tprintf(
|
"Expected private key %s round-trip, got %s",
|
||||||
"Expected private key %s round-trip, got %s",
|
v.priv_key,
|
||||||
v.priv_key,
|
string(hex.encode(key_bytes[:], context.temp_allocator)),
|
||||||
string(hex.encode(key_bytes[:], context.temp_allocator)),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
pub_key: ed25519.Public_Key
|
pub_key: ed25519.Public_Key
|
||||||
ok = ed25519.public_key_set_bytes(&pub_key, pub_bytes)
|
ok = ed25519.public_key_set_bytes(&pub_key, pub_bytes)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
ok,
|
ok,
|
||||||
fmt.tprintf(
|
"Expected %s to be a valid public key (priv->pub: %s)",
|
||||||
"Expected %s to be a valid public key (priv->pub: %s)",
|
v.pub_key,
|
||||||
v.pub_key,
|
string(hex.encode(priv_key._pub_key._b[:], context.temp_allocator)),
|
||||||
string(hex.encode(priv_key._pub_key._b[:], context.temp_allocator)),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ed25519.public_key_bytes(&pub_key, key_bytes[:])
|
ed25519.public_key_bytes(&pub_key, key_bytes[:])
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
ok,
|
ok,
|
||||||
fmt.tprintf(
|
"Expected public key %s round-trip, got %s",
|
||||||
"Expected public key %s round-trip, got %s",
|
v.pub_key,
|
||||||
v.pub_key,
|
string(hex.encode(key_bytes[:], context.temp_allocator)),
|
||||||
string(hex.encode(key_bytes[:], context.temp_allocator)),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
sig: [ed25519.SIGNATURE_SIZE]byte
|
sig: [ed25519.SIGNATURE_SIZE]byte
|
||||||
ed25519.sign(&priv_key, msg_bytes, sig[:])
|
ed25519.sign(&priv_key, msg_bytes, sig[:])
|
||||||
x := string(hex.encode(sig[:], context.temp_allocator))
|
x := string(hex.encode(sig[:], context.temp_allocator))
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
x == v.sig,
|
x == v.sig,
|
||||||
fmt.tprintf(
|
"Expected %s for sign(%s, %s), got %s",
|
||||||
"Expected %s for sign(%s, %s), got %s",
|
v.sig,
|
||||||
v.sig,
|
v.priv_key,
|
||||||
v.priv_key,
|
v.msg,
|
||||||
v.msg,
|
x,
|
||||||
x,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes)
|
ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
ok,
|
ok,
|
||||||
fmt.tprintf(
|
"Expected true for verify(%s, %s, %s)",
|
||||||
"Expected true for verify(%s, %s, %s)",
|
v.pub_key,
|
||||||
v.pub_key,
|
v.msg,
|
||||||
v.msg,
|
v.sig,
|
||||||
v.sig,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ok = ed25519.verify(&priv_key._pub_key, msg_bytes, sig_bytes)
|
ok = ed25519.verify(&priv_key._pub_key, msg_bytes, sig_bytes)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
ok,
|
ok,
|
||||||
fmt.tprintf(
|
"Expected true for verify(pub(%s), %s %s)",
|
||||||
"Expected true for verify(pub(%s), %s %s)",
|
v.priv_key,
|
||||||
v.priv_key,
|
v.msg,
|
||||||
v.msg,
|
v.sig,
|
||||||
v.sig,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Corrupt the message and make sure verification fails.
|
// Corrupt the message and make sure verification fails.
|
||||||
@@ -493,15 +440,13 @@ test_ed25519 :: proc(t: ^testing.T) {
|
|||||||
msg_bytes[0] = msg_bytes[0] ~ 69
|
msg_bytes[0] = msg_bytes[0] ~ 69
|
||||||
}
|
}
|
||||||
ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes)
|
ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
ok == false,
|
ok == false,
|
||||||
fmt.tprintf(
|
"Expected false for verify(%s, %s (corrupted), %s)",
|
||||||
"Expected false for verify(%s, %s (corrupted), %s)",
|
v.pub_key,
|
||||||
v.pub_key,
|
v.msg,
|
||||||
v.msg,
|
v.sig,
|
||||||
v.sig,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,15 +579,13 @@ test_ed25519 :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
pub_key: ed25519.Public_Key
|
pub_key: ed25519.Public_Key
|
||||||
ok := ed25519.public_key_set_bytes(&pub_key, pub_bytes)
|
ok := ed25519.public_key_set_bytes(&pub_key, pub_bytes)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
ok == v.pub_key_ok,
|
ok == v.pub_key_ok,
|
||||||
fmt.tprintf(
|
"speccheck/%d: Expected %s to be a (in)valid public key, got %v",
|
||||||
"speccheck/%d: Expected %s to be a (in)valid public key, got %v",
|
i,
|
||||||
i,
|
v.pub_key,
|
||||||
v.pub_key,
|
ok,
|
||||||
ok,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// If A is rejected for being non-canonical, skip signature check.
|
// If A is rejected for being non-canonical, skip signature check.
|
||||||
@@ -651,17 +594,15 @@ test_ed25519 :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes)
|
ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
ok == v.sig_ok,
|
ok == v.sig_ok,
|
||||||
fmt.tprintf(
|
"speccheck/%d Expected %v for verify(%s, %s, %s)",
|
||||||
"speccheck/%d Expected %v for verify(%s, %s, %s)",
|
i,
|
||||||
i,
|
v.sig_ok,
|
||||||
v.sig_ok,
|
v.pub_key,
|
||||||
v.pub_key,
|
v.msg,
|
||||||
v.msg,
|
v.sig,
|
||||||
v.sig,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// If the signature is accepted, skip the relaxed signature check.
|
// If the signature is accepted, skip the relaxed signature check.
|
||||||
@@ -670,25 +611,21 @@ test_ed25519 :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes, true)
|
ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes, true)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
ok == v.sig_ok_relaxed,
|
ok == v.sig_ok_relaxed,
|
||||||
fmt.tprintf(
|
"speccheck/%d Expected %v for verify(%s, %s, %s, true)",
|
||||||
"speccheck/%d Expected %v for verify(%s, %s, %s, true)",
|
i,
|
||||||
i,
|
v.sig_ok_relaxed,
|
||||||
v.sig_ok_relaxed,
|
v.pub_key,
|
||||||
v.pub_key,
|
v.msg,
|
||||||
v.msg,
|
v.sig,
|
||||||
v.sig,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_x25519 :: proc(t: ^testing.T) {
|
test_x25519 :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing X25519")
|
|
||||||
|
|
||||||
// Local copy of this so that the base point doesn't need to be exported.
|
// Local copy of this so that the base point doesn't need to be exported.
|
||||||
_BASE_POINT: [32]byte = {
|
_BASE_POINT: [32]byte = {
|
||||||
9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
@@ -720,17 +657,15 @@ test_x25519 :: proc(t: ^testing.T) {
|
|||||||
x25519.scalarmult(derived_point[:], scalar[:], point[:])
|
x25519.scalarmult(derived_point[:], scalar[:], point[:])
|
||||||
derived_point_str := string(hex.encode(derived_point[:], context.temp_allocator))
|
derived_point_str := string(hex.encode(derived_point[:], context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
derived_point_str == v.product,
|
derived_point_str == v.product,
|
||||||
fmt.tprintf(
|
"Expected %s for %s * %s, but got %s instead",
|
||||||
"Expected %s for %s * %s, but got %s instead",
|
v.product,
|
||||||
v.product,
|
v.scalar,
|
||||||
v.scalar,
|
v.point,
|
||||||
v.point,
|
derived_point_str,
|
||||||
derived_point_str,
|
)
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Abuse the test vectors to sanity-check the scalar-basepoint multiply.
|
// Abuse the test vectors to sanity-check the scalar-basepoint multiply.
|
||||||
p1, p2: [x25519.POINT_SIZE]byte
|
p1, p2: [x25519.POINT_SIZE]byte
|
||||||
@@ -738,15 +673,13 @@ test_x25519 :: proc(t: ^testing.T) {
|
|||||||
x25519.scalarmult(p2[:], scalar[:], _BASE_POINT[:])
|
x25519.scalarmult(p2[:], scalar[:], _BASE_POINT[:])
|
||||||
p1_str := string(hex.encode(p1[:], context.temp_allocator))
|
p1_str := string(hex.encode(p1[:], context.temp_allocator))
|
||||||
p2_str := string(hex.encode(p2[:], context.temp_allocator))
|
p2_str := string(hex.encode(p2[:], context.temp_allocator))
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
p1_str == p2_str,
|
p1_str == p2_str,
|
||||||
fmt.tprintf(
|
"Expected %s for %s * basepoint, but got %s instead",
|
||||||
"Expected %s for %s * basepoint, but got %s instead",
|
p2_str,
|
||||||
p2_str,
|
v.scalar,
|
||||||
v.scalar,
|
p1_str,
|
||||||
p1_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -763,4 +696,4 @@ fe_str :: proc(fe: ^field.Tight_Field_Element) -> string {
|
|||||||
b: [32]byte
|
b: [32]byte
|
||||||
field.fe_to_bytes(&b, fe)
|
field.fe_to_bytes(&b, fe)
|
||||||
return string(hex.encode(b[:], context.temp_allocator))
|
return string(hex.encode(b[:], context.temp_allocator))
|
||||||
}
|
}
|
||||||
@@ -3,23 +3,17 @@ package test_core_crypto
|
|||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
import "core:bytes"
|
import "core:bytes"
|
||||||
import "core:encoding/hex"
|
import "core:encoding/hex"
|
||||||
import "core:fmt"
|
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
|
|
||||||
import "core:crypto/hash"
|
import "core:crypto/hash"
|
||||||
|
|
||||||
import tc "tests:common"
|
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_hash :: proc(t: ^testing.T) {
|
test_hash :: proc(t: ^testing.T) {
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
tc.log(t, "Testing Hashes")
|
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// - Stick the test vectors in a JSON file or something.
|
// - Stick the test vectors in a JSON file or something.
|
||||||
data_1_000_000_a := strings.repeat("a", 1_000_000)
|
data_1_000_000_a := strings.repeat("a", 1_000_000, context.temp_allocator)
|
||||||
|
|
||||||
digest: [hash.MAX_DIGEST_SIZE]byte
|
digest: [hash.MAX_DIGEST_SIZE]byte
|
||||||
test_vectors := []struct{
|
test_vectors := []struct{
|
||||||
@@ -496,16 +490,14 @@ test_hash :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
dst_str := string(hex.encode(dst, context.temp_allocator))
|
dst_str := string(hex.encode(dst, context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
dst_str == v.hash,
|
dst_str == v.hash,
|
||||||
fmt.tprintf(
|
"%s/incremental: Expected: %s for input of %s, but got %s instead",
|
||||||
"%s/incremental: Expected: %s for input of %s, but got %s instead",
|
algo_name,
|
||||||
algo_name,
|
v.hash,
|
||||||
v.hash,
|
v.str,
|
||||||
v.str,
|
dst_str,
|
||||||
dst_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,25 +513,21 @@ test_hash :: proc(t: ^testing.T) {
|
|||||||
// still correct.
|
// still correct.
|
||||||
digest_sz := hash.DIGEST_SIZES[algo]
|
digest_sz := hash.DIGEST_SIZES[algo]
|
||||||
block_sz := hash.BLOCK_SIZES[algo]
|
block_sz := hash.BLOCK_SIZES[algo]
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
digest_sz <= hash.MAX_DIGEST_SIZE,
|
digest_sz <= hash.MAX_DIGEST_SIZE,
|
||||||
fmt.tprintf(
|
"%s: Digest size %d exceeds max %d",
|
||||||
"%s: Digest size %d exceeds max %d",
|
algo_name,
|
||||||
algo_name,
|
digest_sz,
|
||||||
digest_sz,
|
hash.MAX_DIGEST_SIZE,
|
||||||
hash.MAX_DIGEST_SIZE,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
block_sz <= hash.MAX_BLOCK_SIZE,
|
block_sz <= hash.MAX_BLOCK_SIZE,
|
||||||
fmt.tprintf(
|
"%s: Block size %d exceeds max %d",
|
||||||
"%s: Block size %d exceeds max %d",
|
algo_name,
|
||||||
algo_name,
|
block_sz,
|
||||||
block_sz,
|
hash.MAX_BLOCK_SIZE,
|
||||||
hash.MAX_BLOCK_SIZE,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Exercise most of the happy-path for the high level interface.
|
// Exercise most of the happy-path for the high level interface.
|
||||||
@@ -553,15 +541,13 @@ test_hash :: proc(t: ^testing.T) {
|
|||||||
a_str := string(hex.encode(digest_a, context.temp_allocator))
|
a_str := string(hex.encode(digest_a, context.temp_allocator))
|
||||||
b_str := string(hex.encode(digest_b, context.temp_allocator))
|
b_str := string(hex.encode(digest_b, context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
a_str == b_str,
|
a_str == b_str,
|
||||||
fmt.tprintf(
|
"%s/cmp: Expected: %s (hash_stream) == %s (hash_bytes)",
|
||||||
"%s/cmp: Expected: %s (hash_stream) == %s (hash_bytes)",
|
algo_name,
|
||||||
algo_name,
|
a_str,
|
||||||
a_str,
|
b_str,
|
||||||
b_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Exercise the rolling digest functionality, which also covers
|
// Exercise the rolling digest functionality, which also covers
|
||||||
@@ -571,25 +557,21 @@ test_hash :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
api_algo := hash.algorithm(&ctx)
|
api_algo := hash.algorithm(&ctx)
|
||||||
api_digest_size := hash.digest_size(&ctx)
|
api_digest_size := hash.digest_size(&ctx)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
algo == api_algo,
|
algo == api_algo,
|
||||||
fmt.tprintf(
|
"%s/algorithm: Expected: %v but got %v instead",
|
||||||
"%s/algorithm: Expected: %v but got %v instead",
|
algo_name,
|
||||||
algo_name,
|
algo,
|
||||||
algo,
|
api_algo,
|
||||||
api_algo,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
hash.DIGEST_SIZES[algo] == api_digest_size,
|
hash.DIGEST_SIZES[algo] == api_digest_size,
|
||||||
fmt.tprintf(
|
"%s/digest_size: Expected: %d but got %d instead",
|
||||||
"%s/digest_size: Expected: %d but got %d instead",
|
algo_name,
|
||||||
algo_name,
|
hash.DIGEST_SIZES[algo],
|
||||||
hash.DIGEST_SIZES[algo],
|
api_digest_size,
|
||||||
api_digest_size,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
hash.update(&ctx, digest_a)
|
hash.update(&ctx, digest_a)
|
||||||
@@ -604,16 +586,14 @@ test_hash :: proc(t: ^testing.T) {
|
|||||||
b_str = string(hex.encode(digest_b, context.temp_allocator))
|
b_str = string(hex.encode(digest_b, context.temp_allocator))
|
||||||
c_str := string(hex.encode(digest_c, context.temp_allocator))
|
c_str := string(hex.encode(digest_c, context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
a_str == b_str && b_str == c_str,
|
a_str == b_str && b_str == c_str,
|
||||||
fmt.tprintf(
|
"%s/rolling: Expected: %s (first) == %s (second) == %s (third)",
|
||||||
"%s/rolling: Expected: %s (first) == %s (second) == %s (third)",
|
algo_name,
|
||||||
algo_name,
|
a_str,
|
||||||
a_str,
|
b_str,
|
||||||
b_str,
|
c_str,
|
||||||
c_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,28 +2,14 @@ package test_core_crypto
|
|||||||
|
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
import "core:encoding/hex"
|
import "core:encoding/hex"
|
||||||
import "core:fmt"
|
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
|
|
||||||
import "core:crypto/hash"
|
import "core:crypto/hash"
|
||||||
import "core:crypto/hkdf"
|
import "core:crypto/hkdf"
|
||||||
import "core:crypto/pbkdf2"
|
import "core:crypto/pbkdf2"
|
||||||
|
|
||||||
import tc "tests:common"
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_kdf :: proc(t: ^testing.T) {
|
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
||||||
|
|
||||||
tc.log(t, "Testing KDFs")
|
|
||||||
|
|
||||||
test_hkdf(t)
|
|
||||||
test_pbkdf2(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_hkdf :: proc(t: ^testing.T) {
|
test_hkdf :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing HKDF")
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
tmp: [128]byte // Good enough.
|
tmp: [128]byte // Good enough.
|
||||||
|
|
||||||
@@ -70,25 +56,23 @@ test_hkdf :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
dst_str := string(hex.encode(dst, context.temp_allocator))
|
dst_str := string(hex.encode(dst, context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
dst_str == v.okm,
|
dst_str == v.okm,
|
||||||
fmt.tprintf(
|
"HKDF-%s: Expected: %s for input of (%s, %s, %s), but got %s instead",
|
||||||
"HKDF-%s: Expected: %s for input of (%s, %s, %s), but got %s instead",
|
algo_name,
|
||||||
algo_name,
|
v.okm,
|
||||||
v.okm,
|
v.ikm,
|
||||||
v.ikm,
|
v.salt,
|
||||||
v.salt,
|
v.info,
|
||||||
v.info,
|
dst_str,
|
||||||
dst_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_pbkdf2 :: proc(t: ^testing.T) {
|
test_pbkdf2 :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing PBKDF2")
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
tmp: [64]byte // 512-bits is enough for every output for now.
|
tmp: [64]byte // 512-bits is enough for every output for now.
|
||||||
|
|
||||||
@@ -174,18 +158,16 @@ test_pbkdf2 :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
dst_str := string(hex.encode(dst, context.temp_allocator))
|
dst_str := string(hex.encode(dst, context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
dst_str == v.dk,
|
dst_str == v.dk,
|
||||||
fmt.tprintf(
|
"HMAC-%s: Expected: %s for input of (%s, %s, %d), but got %s instead",
|
||||||
"HMAC-%s: Expected: %s for input of (%s, %s, %d), but got %s instead",
|
algo_name,
|
||||||
algo_name,
|
v.dk,
|
||||||
v.dk,
|
v.password,
|
||||||
v.password,
|
v.salt,
|
||||||
v.salt,
|
v.iterations,
|
||||||
v.iterations,
|
dst_str,
|
||||||
dst_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,30 +2,17 @@ package test_core_crypto
|
|||||||
|
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
import "core:encoding/hex"
|
import "core:encoding/hex"
|
||||||
import "core:fmt"
|
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
|
|
||||||
import "core:crypto/hash"
|
import "core:crypto/hash"
|
||||||
import "core:crypto/hmac"
|
import "core:crypto/hmac"
|
||||||
import "core:crypto/poly1305"
|
import "core:crypto/poly1305"
|
||||||
import "core:crypto/siphash"
|
import "core:crypto/siphash"
|
||||||
|
|
||||||
import tc "tests:common"
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_mac :: proc(t: ^testing.T) {
|
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
||||||
|
|
||||||
tc.log(t, "Testing MACs")
|
|
||||||
|
|
||||||
test_hmac(t)
|
|
||||||
test_poly1305(t)
|
|
||||||
test_siphash_2_4(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_hmac :: proc(t: ^testing.T) {
|
test_hmac :: proc(t: ^testing.T) {
|
||||||
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
// Test cases pulled out of RFC 6234, note that HMAC is a generic
|
// Test cases pulled out of RFC 6234, note that HMAC is a generic
|
||||||
// construct so as long as the underlying hash is correct and all
|
// construct so as long as the underlying hash is correct and all
|
||||||
// the code paths are covered the implementation is "fine", so
|
// the code paths are covered the implementation is "fine", so
|
||||||
@@ -86,40 +73,36 @@ test_hmac :: proc(t: ^testing.T) {
|
|||||||
msg_str := string(hex.encode(msg, context.temp_allocator))
|
msg_str := string(hex.encode(msg, context.temp_allocator))
|
||||||
dst_str := string(hex.encode(dst[:tag_len], context.temp_allocator))
|
dst_str := string(hex.encode(dst[:tag_len], context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
dst_str == expected_str,
|
dst_str == expected_str,
|
||||||
fmt.tprintf(
|
"%s/incremental: Expected: %s for input of %s - %s, but got %s instead",
|
||||||
"%s/incremental: Expected: %s for input of %s - %s, but got %s instead",
|
algo_name,
|
||||||
algo_name,
|
tags_sha256[i],
|
||||||
tags_sha256[i],
|
key_str,
|
||||||
key_str,
|
msg_str,
|
||||||
msg_str,
|
dst_str,
|
||||||
dst_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
hmac.sum(algo, dst, msg, key)
|
hmac.sum(algo, dst, msg, key)
|
||||||
oneshot_str := string(hex.encode(dst[:tag_len], context.temp_allocator))
|
oneshot_str := string(hex.encode(dst[:tag_len], context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
oneshot_str == expected_str,
|
oneshot_str == expected_str,
|
||||||
fmt.tprintf(
|
"%s/oneshot: Expected: %s for input of %s - %s, but got %s instead",
|
||||||
"%s/oneshot: Expected: %s for input of %s - %s, but got %s instead",
|
algo_name,
|
||||||
algo_name,
|
tags_sha256[i],
|
||||||
tags_sha256[i],
|
key_str,
|
||||||
key_str,
|
msg_str,
|
||||||
msg_str,
|
oneshot_str,
|
||||||
oneshot_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_poly1305 :: proc(t: ^testing.T) {
|
test_poly1305 :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing poly1305")
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
// Test cases taken from poly1305-donna.
|
// Test cases taken from poly1305-donna.
|
||||||
key := [poly1305.KEY_SIZE]byte {
|
key := [poly1305.KEY_SIZE]byte {
|
||||||
@@ -157,16 +140,17 @@ test_poly1305 :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
// Verify - oneshot + compare
|
// Verify - oneshot + compare
|
||||||
ok := poly1305.verify(tag[:], msg[:], key[:])
|
ok := poly1305.verify(tag[:], msg[:], key[:])
|
||||||
tc.expect(t, ok, "oneshot verify call failed")
|
testing.expect(t, ok, "oneshot verify call failed")
|
||||||
|
|
||||||
// Sum - oneshot
|
// Sum - oneshot
|
||||||
derived_tag: [poly1305.TAG_SIZE]byte
|
derived_tag: [poly1305.TAG_SIZE]byte
|
||||||
poly1305.sum(derived_tag[:], msg[:], key[:])
|
poly1305.sum(derived_tag[:], msg[:], key[:])
|
||||||
derived_tag_str := string(hex.encode(derived_tag[:], context.temp_allocator))
|
derived_tag_str := string(hex.encode(derived_tag[:], context.temp_allocator))
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
derived_tag_str == tag_str,
|
derived_tag_str == tag_str,
|
||||||
fmt.tprintf("Expected %s for sum(msg, key), but got %s instead", tag_str, derived_tag_str),
|
"Expected %s for sum(msg, key), but got %s instead",
|
||||||
|
tag_str, derived_tag_str,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Incremental
|
// Incremental
|
||||||
@@ -182,21 +166,16 @@ test_poly1305 :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
poly1305.final(&ctx, derived_tag[:])
|
poly1305.final(&ctx, derived_tag[:])
|
||||||
derived_tag_str = string(hex.encode(derived_tag[:], context.temp_allocator))
|
derived_tag_str = string(hex.encode(derived_tag[:], context.temp_allocator))
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
derived_tag_str == tag_str,
|
derived_tag_str == tag_str,
|
||||||
fmt.tprintf(
|
"Expected %s for init/update/final - incremental, but got %s instead",
|
||||||
"Expected %s for init/update/final - incremental, but got %s instead",
|
tag_str, derived_tag_str,
|
||||||
tag_str,
|
|
||||||
derived_tag_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_siphash_2_4 :: proc(t: ^testing.T) {
|
test_siphash_2_4 :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing SipHash-2-4")
|
|
||||||
|
|
||||||
// Test vectors from
|
// Test vectors from
|
||||||
// https://github.com/veorq/SipHash/blob/master/vectors.h
|
// https://github.com/veorq/SipHash/blob/master/vectors.h
|
||||||
test_vectors := [?]u64 {
|
test_vectors := [?]u64 {
|
||||||
@@ -225,6 +204,7 @@ test_siphash_2_4 :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
for i in 0 ..< len(test_vectors) {
|
for i in 0 ..< len(test_vectors) {
|
||||||
data := make([]byte, i)
|
data := make([]byte, i)
|
||||||
|
defer delete(data)
|
||||||
for j in 0 ..< i {
|
for j in 0 ..< i {
|
||||||
data[j] = byte(j)
|
data[j] = byte(j)
|
||||||
}
|
}
|
||||||
@@ -232,15 +212,13 @@ test_siphash_2_4 :: proc(t: ^testing.T) {
|
|||||||
vector := test_vectors[i]
|
vector := test_vectors[i]
|
||||||
computed := siphash.sum_2_4(data[:], key[:])
|
computed := siphash.sum_2_4(data[:], key[:])
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
computed == vector,
|
computed == vector,
|
||||||
fmt.tprintf(
|
"Expected: 0x%x for input of %v, but got 0x%x instead",
|
||||||
"Expected: 0x%x for input of %v, but got 0x%x instead",
|
vector,
|
||||||
vector,
|
data,
|
||||||
data,
|
computed,
|
||||||
computed,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,30 +2,14 @@ package test_core_crypto
|
|||||||
|
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
import "core:encoding/hex"
|
import "core:encoding/hex"
|
||||||
import "core:fmt"
|
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
|
|
||||||
import "core:crypto/kmac"
|
import "core:crypto/kmac"
|
||||||
import "core:crypto/shake"
|
import "core:crypto/shake"
|
||||||
import "core:crypto/tuplehash"
|
import "core:crypto/tuplehash"
|
||||||
|
|
||||||
import tc "tests:common"
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
test_sha3_variants :: proc(t: ^testing.T) {
|
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
||||||
|
|
||||||
tc.log(t, "Testing SHA3 derived functions")
|
|
||||||
|
|
||||||
test_shake(t)
|
|
||||||
test_cshake(t)
|
|
||||||
test_tuplehash(t)
|
|
||||||
test_kmac(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_shake :: proc(t: ^testing.T) {
|
test_shake :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing SHAKE")
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
test_vectors := []struct {
|
test_vectors := []struct {
|
||||||
sec_strength: int,
|
sec_strength: int,
|
||||||
@@ -67,23 +51,21 @@ test_shake :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
dst_str := string(hex.encode(dst, context.temp_allocator))
|
dst_str := string(hex.encode(dst, context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
dst_str == v.output,
|
dst_str == v.output,
|
||||||
fmt.tprintf(
|
"SHAKE%d: Expected: %s for input of %s, but got %s instead",
|
||||||
"SHAKE%d: Expected: %s for input of %s, but got %s instead",
|
v.sec_strength,
|
||||||
v.sec_strength,
|
v.output,
|
||||||
v.output,
|
v.str,
|
||||||
v.str,
|
dst_str,
|
||||||
dst_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_cshake :: proc(t: ^testing.T) {
|
test_cshake :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing cSHAKE")
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
test_vectors := []struct {
|
test_vectors := []struct {
|
||||||
sec_strength: int,
|
sec_strength: int,
|
||||||
@@ -135,29 +117,27 @@ test_cshake :: proc(t: ^testing.T) {
|
|||||||
shake.init_cshake_256(&ctx, domainsep)
|
shake.init_cshake_256(&ctx, domainsep)
|
||||||
}
|
}
|
||||||
|
|
||||||
data, _ := hex.decode(transmute([]byte)(v.str))
|
data, _ := hex.decode(transmute([]byte)(v.str), context.temp_allocator)
|
||||||
shake.write(&ctx, data)
|
shake.write(&ctx, data)
|
||||||
shake.read(&ctx, dst)
|
shake.read(&ctx, dst)
|
||||||
|
|
||||||
dst_str := string(hex.encode(dst, context.temp_allocator))
|
dst_str := string(hex.encode(dst, context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
dst_str == v.output,
|
dst_str == v.output,
|
||||||
fmt.tprintf(
|
"cSHAKE%d: Expected: %s for input of %s, but got %s instead",
|
||||||
"cSHAKE%d: Expected: %s for input of %s, but got %s instead",
|
v.sec_strength,
|
||||||
v.sec_strength,
|
v.output,
|
||||||
v.output,
|
v.str,
|
||||||
v.str,
|
dst_str,
|
||||||
dst_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_tuplehash :: proc(t: ^testing.T) {
|
test_tuplehash :: proc(t: ^testing.T) {
|
||||||
tc.log(t, "Testing TupleHash(XOF)")
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
test_vectors := []struct {
|
test_vectors := []struct {
|
||||||
sec_strength: int,
|
sec_strength: int,
|
||||||
@@ -317,7 +297,7 @@ test_tuplehash :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for e in v.tuple {
|
for e in v.tuple {
|
||||||
data, _ := hex.decode(transmute([]byte)(e))
|
data, _ := hex.decode(transmute([]byte)(e), context.temp_allocator)
|
||||||
tuplehash.write_element(&ctx, data)
|
tuplehash.write_element(&ctx, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,24 +312,22 @@ test_tuplehash :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
dst_str := string(hex.encode(dst, context.temp_allocator))
|
dst_str := string(hex.encode(dst, context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
dst_str == v.output,
|
dst_str == v.output,
|
||||||
fmt.tprintf(
|
"TupleHash%s%d: Expected: %s for input of %v, but got %s instead",
|
||||||
"TupleHash%s%d: Expected: %s for input of %v, but got %s instead",
|
suffix,
|
||||||
suffix,
|
v.sec_strength,
|
||||||
v.sec_strength,
|
v.output,
|
||||||
v.output,
|
v.tuple,
|
||||||
v.tuple,
|
dst_str,
|
||||||
dst_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
test_kmac :: proc(t:^testing.T) {
|
test_kmac :: proc(t:^testing.T) {
|
||||||
tc.log(t, "Testing KMAC")
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
test_vectors := []struct {
|
test_vectors := []struct {
|
||||||
sec_strength: int,
|
sec_strength: int,
|
||||||
@@ -410,7 +388,7 @@ test_kmac :: proc(t:^testing.T) {
|
|||||||
for v in test_vectors {
|
for v in test_vectors {
|
||||||
dst := make([]byte, len(v.output) / 2, context.temp_allocator)
|
dst := make([]byte, len(v.output) / 2, context.temp_allocator)
|
||||||
|
|
||||||
key, _ := hex.decode(transmute([]byte)(v.key))
|
key, _ := hex.decode(transmute([]byte)(v.key), context.temp_allocator)
|
||||||
domainsep := transmute([]byte)(v.domainsep)
|
domainsep := transmute([]byte)(v.domainsep)
|
||||||
|
|
||||||
ctx: kmac.Context
|
ctx: kmac.Context
|
||||||
@@ -421,24 +399,22 @@ test_kmac :: proc(t:^testing.T) {
|
|||||||
kmac.init_256(&ctx, key, domainsep)
|
kmac.init_256(&ctx, key, domainsep)
|
||||||
}
|
}
|
||||||
|
|
||||||
data, _ := hex.decode(transmute([]byte)(v.msg))
|
data, _ := hex.decode(transmute([]byte)(v.msg), context.temp_allocator)
|
||||||
kmac.update(&ctx, data)
|
kmac.update(&ctx, data)
|
||||||
kmac.final(&ctx, dst)
|
kmac.final(&ctx, dst)
|
||||||
|
|
||||||
dst_str := string(hex.encode(dst, context.temp_allocator))
|
dst_str := string(hex.encode(dst, context.temp_allocator))
|
||||||
|
|
||||||
tc.expect(
|
testing.expectf(
|
||||||
t,
|
t,
|
||||||
dst_str == v.output,
|
dst_str == v.output,
|
||||||
fmt.tprintf(
|
"KMAC%d: Expected: %s for input of (%s, %s, %s), but got %s instead",
|
||||||
"KMAC%d: Expected: %s for input of (%s, %s, %s), but got %s instead",
|
v.sec_strength,
|
||||||
v.sec_strength,
|
v.output,
|
||||||
v.output,
|
v.key,
|
||||||
v.key,
|
v.domainsep,
|
||||||
v.domainsep,
|
v.msg,
|
||||||
v.msg,
|
dst_str,
|
||||||
dst_str,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ package test_core_crypto
|
|||||||
|
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
import "core:encoding/hex"
|
import "core:encoding/hex"
|
||||||
import "core:fmt"
|
import "core:log"
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
import "core:time"
|
import "core:time"
|
||||||
|
|
||||||
@@ -13,16 +13,11 @@ import "core:crypto/ed25519"
|
|||||||
import "core:crypto/poly1305"
|
import "core:crypto/poly1305"
|
||||||
import "core:crypto/x25519"
|
import "core:crypto/x25519"
|
||||||
|
|
||||||
import tc "tests:common"
|
|
||||||
|
|
||||||
// Cryptographic primitive benchmarks.
|
// Cryptographic primitive benchmarks.
|
||||||
|
|
||||||
@(test)
|
@(test)
|
||||||
bench_crypto :: proc(t: ^testing.T) {
|
bench_crypto :: proc(t: ^testing.T) {
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
fmt.println("Starting benchmarks:")
|
|
||||||
|
|
||||||
bench_chacha20(t)
|
bench_chacha20(t)
|
||||||
bench_poly1305(t)
|
bench_poly1305(t)
|
||||||
bench_chacha20poly1305(t)
|
bench_chacha20poly1305(t)
|
||||||
@@ -157,8 +152,8 @@ _benchmark_aes256_gcm :: proc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
benchmark_print :: proc(name: string, options: ^time.Benchmark_Options) {
|
benchmark_print :: proc(name: string, options: ^time.Benchmark_Options) {
|
||||||
fmt.printf(
|
log.infof(
|
||||||
"\t[%v] %v rounds, %v bytes processed in %v ns\n\t\t%5.3f rounds/s, %5.3f MiB/s\n",
|
"\n\t[%v] %v rounds, %v bytes processed in %v ns\n\t\t%5.3f rounds/s, %5.3f MiB/s",
|
||||||
name,
|
name,
|
||||||
options.rounds,
|
options.rounds,
|
||||||
options.processed,
|
options.processed,
|
||||||
@@ -179,19 +174,19 @@ bench_chacha20 :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
err := time.benchmark(options, context.allocator)
|
||||||
tc.expect(t, err == nil, name)
|
testing.expect(t, err == nil, name)
|
||||||
benchmark_print(name, options)
|
benchmark_print(name, options)
|
||||||
|
|
||||||
name = "ChaCha20 1024 bytes"
|
name = "ChaCha20 1024 bytes"
|
||||||
options.bytes = 1024
|
options.bytes = 1024
|
||||||
err = time.benchmark(options, context.allocator)
|
err = time.benchmark(options, context.allocator)
|
||||||
tc.expect(t, err == nil, name)
|
testing.expect(t, err == nil, name)
|
||||||
benchmark_print(name, options)
|
benchmark_print(name, options)
|
||||||
|
|
||||||
name = "ChaCha20 65536 bytes"
|
name = "ChaCha20 65536 bytes"
|
||||||
options.bytes = 65536
|
options.bytes = 65536
|
||||||
err = time.benchmark(options, context.allocator)
|
err = time.benchmark(options, context.allocator)
|
||||||
tc.expect(t, err == nil, name)
|
testing.expect(t, err == nil, name)
|
||||||
benchmark_print(name, options)
|
benchmark_print(name, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,13 +201,13 @@ bench_poly1305 :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
err := time.benchmark(options, context.allocator)
|
||||||
tc.expect(t, err == nil, name)
|
testing.expect(t, err == nil, name)
|
||||||
benchmark_print(name, options)
|
benchmark_print(name, options)
|
||||||
|
|
||||||
name = "Poly1305 1024 zero bytes"
|
name = "Poly1305 1024 zero bytes"
|
||||||
options.bytes = 1024
|
options.bytes = 1024
|
||||||
err = time.benchmark(options, context.allocator)
|
err = time.benchmark(options, context.allocator)
|
||||||
tc.expect(t, err == nil, name)
|
testing.expect(t, err == nil, name)
|
||||||
benchmark_print(name, options)
|
benchmark_print(name, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,19 +222,19 @@ bench_chacha20poly1305 :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
err := time.benchmark(options, context.allocator)
|
||||||
tc.expect(t, err == nil, name)
|
testing.expect(t, err == nil, name)
|
||||||
benchmark_print(name, options)
|
benchmark_print(name, options)
|
||||||
|
|
||||||
name = "chacha20poly1305 1024 bytes"
|
name = "chacha20poly1305 1024 bytes"
|
||||||
options.bytes = 1024
|
options.bytes = 1024
|
||||||
err = time.benchmark(options, context.allocator)
|
err = time.benchmark(options, context.allocator)
|
||||||
tc.expect(t, err == nil, name)
|
testing.expect(t, err == nil, name)
|
||||||
benchmark_print(name, options)
|
benchmark_print(name, options)
|
||||||
|
|
||||||
name = "chacha20poly1305 65536 bytes"
|
name = "chacha20poly1305 65536 bytes"
|
||||||
options.bytes = 65536
|
options.bytes = 65536
|
||||||
err = time.benchmark(options, context.allocator)
|
err = time.benchmark(options, context.allocator)
|
||||||
tc.expect(t, err == nil, name)
|
testing.expect(t, err == nil, name)
|
||||||
benchmark_print(name, options)
|
benchmark_print(name, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,19 +260,19 @@ bench_aes256_gcm :: proc(t: ^testing.T) {
|
|||||||
context.user_ptr = &ctx
|
context.user_ptr = &ctx
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
err := time.benchmark(options, context.allocator)
|
||||||
tc.expect(t, err == nil, name)
|
testing.expect(t, err == nil, name)
|
||||||
benchmark_print(name, options)
|
benchmark_print(name, options)
|
||||||
|
|
||||||
name = "AES256-GCM 1024 bytes"
|
name = "AES256-GCM 1024 bytes"
|
||||||
options.bytes = 1024
|
options.bytes = 1024
|
||||||
err = time.benchmark(options, context.allocator)
|
err = time.benchmark(options, context.allocator)
|
||||||
tc.expect(t, err == nil, name)
|
testing.expect(t, err == nil, name)
|
||||||
benchmark_print(name, options)
|
benchmark_print(name, options)
|
||||||
|
|
||||||
name = "AES256-GCM 65536 bytes"
|
name = "AES256-GCM 65536 bytes"
|
||||||
options.bytes = 65536
|
options.bytes = 65536
|
||||||
err = time.benchmark(options, context.allocator)
|
err = time.benchmark(options, context.allocator)
|
||||||
tc.expect(t, err == nil, name)
|
testing.expect(t, err == nil, name)
|
||||||
benchmark_print(name, options)
|
benchmark_print(name, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,12 +288,9 @@ bench_ed25519 :: proc(t: ^testing.T) {
|
|||||||
assert(ok, "private key should deserialize")
|
assert(ok, "private key should deserialize")
|
||||||
}
|
}
|
||||||
elapsed := time.since(start)
|
elapsed := time.since(start)
|
||||||
tc.log(
|
log.infof(
|
||||||
t,
|
"ed25519.private_key_set_bytes: ~%f us/op",
|
||||||
fmt.tprintf(
|
time.duration_microseconds(elapsed) / iters,
|
||||||
"ed25519.private_key_set_bytes: ~%f us/op",
|
|
||||||
time.duration_microseconds(elapsed) / iters,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
pub_bytes := priv_key._pub_key._b[:] // "I know what I am doing"
|
pub_bytes := priv_key._pub_key._b[:] // "I know what I am doing"
|
||||||
@@ -309,12 +301,9 @@ bench_ed25519 :: proc(t: ^testing.T) {
|
|||||||
assert(ok, "public key should deserialize")
|
assert(ok, "public key should deserialize")
|
||||||
}
|
}
|
||||||
elapsed = time.since(start)
|
elapsed = time.since(start)
|
||||||
tc.log(
|
log.infof(
|
||||||
t,
|
"ed25519.public_key_set_bytes: ~%f us/op",
|
||||||
fmt.tprintf(
|
time.duration_microseconds(elapsed) / iters,
|
||||||
"ed25519.public_key_set_bytes: ~%f us/op",
|
|
||||||
time.duration_microseconds(elapsed) / iters,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
msg := "Got a job for you, 621."
|
msg := "Got a job for you, 621."
|
||||||
@@ -325,7 +314,10 @@ bench_ed25519 :: proc(t: ^testing.T) {
|
|||||||
ed25519.sign(&priv_key, msg_bytes, sig_bytes[:])
|
ed25519.sign(&priv_key, msg_bytes, sig_bytes[:])
|
||||||
}
|
}
|
||||||
elapsed = time.since(start)
|
elapsed = time.since(start)
|
||||||
tc.log(t, fmt.tprintf("ed25519.sign: ~%f us/op", time.duration_microseconds(elapsed) / iters))
|
log.infof(
|
||||||
|
"ed25519.sign: ~%f us/op",
|
||||||
|
time.duration_microseconds(elapsed) / iters,
|
||||||
|
)
|
||||||
|
|
||||||
start = time.now()
|
start = time.now()
|
||||||
for i := 0; i < iters; i = i + 1 {
|
for i := 0; i < iters; i = i + 1 {
|
||||||
@@ -333,9 +325,9 @@ bench_ed25519 :: proc(t: ^testing.T) {
|
|||||||
assert(ok, "signature should validate")
|
assert(ok, "signature should validate")
|
||||||
}
|
}
|
||||||
elapsed = time.since(start)
|
elapsed = time.since(start)
|
||||||
tc.log(
|
log.infof(
|
||||||
t,
|
"ed25519.verify: ~%f us/op",
|
||||||
fmt.tprintf("ed25519.verify: ~%f us/op", time.duration_microseconds(elapsed) / iters),
|
time.duration_microseconds(elapsed) / iters,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,8 +346,8 @@ bench_x25519 :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
elapsed := time.since(start)
|
elapsed := time.since(start)
|
||||||
|
|
||||||
tc.log(
|
log.infof(
|
||||||
t,
|
"x25519.scalarmult: ~%f us/op",
|
||||||
fmt.tprintf("x25519.scalarmult: ~%f us/op", time.duration_microseconds(elapsed) / iters),
|
time.duration_microseconds(elapsed) / iters,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,8 @@ import "core:hash"
|
|||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:time"
|
import "core:time"
|
||||||
import "base:runtime"
|
|
||||||
|
|
||||||
TEST_SUITE_PATH :: "assets/PNG"
|
TEST_SUITE_PATH :: ODIN_ROOT + "tests/core/assets/PNG/"
|
||||||
|
|
||||||
I_Error :: image.Error
|
I_Error :: image.Error
|
||||||
|
|
||||||
@@ -1455,10 +1454,9 @@ png_test_no_postproc :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
run_png_suite :: proc(t: ^testing.T, suite: []PNG_Test) {
|
run_png_suite :: proc(t: ^testing.T, suite: []PNG_Test) {
|
||||||
context = runtime.default_context()
|
|
||||||
|
|
||||||
for file in suite {
|
for file in suite {
|
||||||
test_file := strings.concatenate({TEST_SUITE_PATH, "/", file.file, ".png"}, context.temp_allocator)
|
test_file := strings.concatenate({TEST_SUITE_PATH, file.file, ".png"})
|
||||||
|
defer delete(test_file)
|
||||||
|
|
||||||
img: ^png.Image
|
img: ^png.Image
|
||||||
err: png.Error
|
err: png.Error
|
||||||
@@ -1467,10 +1465,6 @@ run_png_suite :: proc(t: ^testing.T, suite: []PNG_Test) {
|
|||||||
for test in file.tests {
|
for test in file.tests {
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
track: mem.Tracking_Allocator
|
|
||||||
mem.tracking_allocator_init(&track, context.allocator)
|
|
||||||
context.allocator = mem.tracking_allocator(&track)
|
|
||||||
|
|
||||||
img, err = png.load(test_file, test.options)
|
img, err = png.load(test_file, test.options)
|
||||||
|
|
||||||
passed := (test.expected_error == nil && err == nil) || (test.expected_error == err)
|
passed := (test.expected_error == nil && err == nil) || (test.expected_error == err)
|
||||||
|
|||||||
Reference in New Issue
Block a user