Unify into a single implementation file

This commit is contained in:
Eric Mertens
2025-09-04 18:30:47 -07:00
parent 51dbdbf415
commit be65d0dd4e
7 changed files with 162 additions and 118 deletions

154
Ascon.cry
View File

@@ -48,11 +48,11 @@ type constraint ValidRnd rnd = rnd <= 16
/// Core permutation function parameterized by a round count. /// Core permutation function parameterized by a round count.
Ascon_p : {rnd} (ValidRnd rnd) => State -> State Ascon_p : {rnd} (ValidRnd rnd) => State -> State
Ascon_p S = foldl p`{rnd} S (drop`{back=rnd} Const) Ascon_p S = foldl round S (drop`{back=rnd} Const)
/// Single round of the Ascon-p permutation. /// Single round of the Ascon-p permutation.
p : {rnd} (ValidRnd rnd) => State -> [64] -> State round : State -> [64] -> State
p S ci = pL (pS (pC S ci)) round S ci = pL (pS (pC S ci))
// 3.1. Internal State // 3.1. Internal State
@@ -149,3 +149,151 @@ wordsToBits M = join (map reverse M)
bitsToWords : {w,n} (fin w) => [w*n] -> [n][w] bitsToWords : {w,n} (fin w) => [w*n] -> [n][w]
bitsToWords M = map reverse (split M) bitsToWords M = map reverse (split M)
// 4. Authenticated Encryption Schema: Ascon-AEAD128
/// Encryption using Ascon-AEAD128
///
/// Parameters:
/// - Key
/// - Nonce
/// - Additional data
/// - Plaintext
///
/// Returns:
/// - Authenticated ciphertext
AEAD128_encrypt : {a, p} (fin a, fin p) => [128] -> [128] -> [a] -> [p] -> [p + 128]
AEAD128_encrypt K N A P = C # T
where
// key and nonce as two 64-bit integers
[K0,K1] = bitsToWords K
[N0,N1] = bitsToWords N
S0 = Ascon_p`{12} [Ascon_AEAD128_IV, K0, K1, N0, N1] ^ [0, 0, 0, K0, K1]
SA = AddAD S0 A
SCs = [XorBlock s p | s <- [SA] # map Ascon_p`{8} SCs | p <- toBlocks P]
C = take (join (map ExtractC SCs))
ST = Ascon_p`{12} (last SCs ^ [0, 0, K0, K1, 0])
T = ExtractT ST ^ K
/// Decryption using Ascon-AEAD128
///
/// Parameters:
/// - Key
/// - Nonce
/// - Additional data
/// - Ciphertext
///
/// Returns:
/// - Some plaintext on success
/// - None when message authentication fails
AEAD128_decrypt : {a, p} (fin a, fin p) => [128] -> [128] -> [a] -> [p + 128] -> Option [p]
AEAD128_decrypt K N A (Cs_ # Cl # T) =
if T == T' then Some P else trace "P" P None
where
// key and nonce as two 64-bit integers
[K0,K1] = bitsToWords K
[N0,N1] = bitsToWords N
S0 = Ascon_p`{12} [Ascon_AEAD128_IV, K0, K1, N0, N1] ^ [0, 0, 0, K0, K1]
SA = AddAD S0 A
Cs = split`{p/128, 128} Cs_
SCs # [SCl] = [SA] # [Ascon_p`{8} (AssignC s c) | s <- SCs | c <- Cs]
Plmask # SCl' = ExtractC SCl
Sl' = AssignC SCl (Cl # (0b1#0 ^ SCl'))
Ps = zipWith (\x y -> ExtractC x ^ y) SCs Cs
Pl = Plmask ^ Cl
P = join Ps # Pl
ST = Ascon_p`{12} (Sl' ^ [0, 0, K0, K1, 0])
T' = ExtractT ST ^ K
AEAD128_encrypt_bytes : {a, p} (fin a, fin p) => [16][8] -> [16][8] -> [a][8] -> [p][8] -> [p + 16][8]
AEAD128_encrypt_bytes K N A P =
bitsToWords (AEAD128_encrypt (wordsToBits K) (wordsToBits N) (wordsToBits A) (wordsToBits P))
AEAD128_decrypt_bytes : {a, p} (fin a, fin p) => [16][8] -> [16][8] -> [a][8] -> [p + 16][8] -> Option ([p][8])
AEAD128_decrypt_bytes K N A C =
case AEAD128_decrypt (wordsToBits K) (wordsToBits N) (wordsToBits A) (wordsToBits C) of
None -> None
Some p -> Some (bitsToWords p)
AddAD : {a} (fin a) => State -> [a] -> State
AddAD S A
| a == 0 => DomainSep S
| a > 0 => DomainSep (foldl AbsorbBlock128 S (toBlocks A))
DomainSep : State -> State
DomainSep [s0, s1, s2, s3, s4] = [s0, s1, s2, s3, s4 ^ 0b1 # 0]
AbsorbBlock128 : State -> [128] -> State
AbsorbBlock128 S X = Ascon_p`{8} (XorBlock S X)
XorBlock : State -> [128] -> State
XorBlock [s0, s1, s2, s3, s4] (xhi # xlo) = [s0 ^ xlo, s1 ^ xhi, s2, s3, s4]
ExtractC : State -> [128]
ExtractC [s0, s1, _, _, _] = wordsToBits [s0, s1]
AssignC : State -> [128] -> State
AssignC [_, _, s2, s3, s4] C = bitsToWords C # [s2, s3, s4]
ExtractT : State -> [128]
ExtractT [_, _, _, s3, s4] = wordsToBits [s3, s4]
Ascon_AEAD128_IV : [64]
Ascon_AEAD128_IV = 0x00001000808c0001
// 5. Hash and eXtendable-Output Functions (XOFs)
hashBlocks : {n} (fin n) => [64] -> [n][64] -> [inf]
hashBlocks IV Ms = wordsToBits [head S | S <- iterate Ascon_p`{12} Sn]
where
S0 = Ascon_p`{12} [IV, 0, 0, 0, 0]
Sn = foldl AbsorbBlock64 S0 Ms
AbsorbBlock64 : State -> [64] -> State
AbsorbBlock64 [s0, s1, s2, s3, s4] X = Ascon_p`{12} [X ^ s0, s1, s2, s3, s4]
/// 5.1. Specification of Ascon-Hash256
Hash256 : {n} (fin n) => [n] -> [256]
Hash256 M = take (hashBlocks Hash256_IV (toBlocks M))
Hash256_bytes : {n} (fin n) => [n][8] -> [32][8]
Hash256_bytes M = bitsToWords (Hash256 (wordsToBits M))
Hash256_IV : [64]
Hash256_IV = 0x0000080100cc0002
// 5.2. Specification of Ascon-XOF128
XOF128 : {r, n} (fin n, fin r) => [n] -> [r]
XOF128 M = take (hashBlocks XOF128_IV (toBlocks M))
XOF128_bytes : {r, n} (fin n, fin r) => [n][8] -> [r][8]
XOF128_bytes M = bitsToWords (XOF128 (wordsToBits M))
XOF128_IV : [64]
XOF128_IV = 0x0000080000cc0003
// 5.3. Specification of Ascon-CXOF128
CXOF128 : {r, c, n} (fin n, fin r, fin c, 64 >= width c) => [c] -> [n] -> [r]
CXOF128 Z M = take (hashBlocks CXOF128_IV Ms)
where
Ms = [`c]
# toBlocks Z
# toBlocks M
CXOF128_bytes : {r, z, n} (fin n, fin r, 61 >= width z) => [z][8] -> [n][8] -> [r][8]
CXOF128_bytes Z M = bitsToWords (CXOF128 (wordsToBits Z) (wordsToBits M))
CXOF128_IV : [64]
CXOF128_IV = 0x0000080000cc0004

View File

@@ -1,51 +0,0 @@
module AsconCipher where
import Ascon
// 4. Authenticated Encryption Schema: Ascon-AEAD128
Ascon_AEAD128 : {a, p} (fin a, fin p) => [128] -> [128] -> [a] -> [p] -> [p + 128]
Ascon_AEAD128 K N A P = C # T
where
// key and nonce as two 64-bit integers
[K0,K1] = bitsToWords K
[N0,N1] = bitsToWords N
S0 = Ascon_p`{12} [Ascon_AEAD128_IV, K0, K1, N0, N1]
^ [0, 0, 0, K0, K1]
SA = AddAD S0 A
SCs = zipWith XorBlock (take ([SA] # map Ascon_p`{8} SCs)) (toBlocks P)
C = take (join (map ExtractC SCs))
ST = Ascon_p`{12} (last SCs ^ [0, 0, K0, K1, 0])
T = ExtractT ST ^ K
Ascon_AEAD128_bytes : {a, p} (fin a, fin p) => [16][8] -> [16][8] -> [a][8] -> [p][8] -> [p + 16][8]
Ascon_AEAD128_bytes K N A P =
bitsToWords (Ascon_AEAD128 (wordsToBits K) (wordsToBits N) (wordsToBits A) (wordsToBits P))
AddAD : {a} (fin a) => State -> [a] -> State
AddAD S A
| a == 0 => DomainSep S
| a > 0 => DomainSep (foldl AbsorbBlock S (toBlocks A))
XorBlock : State -> [128] -> State
XorBlock [s0, s1, s2, s3, s4] (xhi # xlo) = [s0 ^ xlo, s1 ^ xhi, s2, s3, s4]
AbsorbBlock : State -> [128] -> State
AbsorbBlock S X = Ascon_p`{8} (XorBlock S X)
DomainSep : State -> State
DomainSep [s0, s1, s2, s3, s4] = [s0, s1, s2, s3, s4 ^ 0b1 # 0]
ExtractC : State -> [128]
ExtractC [s0, s1, _, _, _] = wordsToBits [s0, s1]
ExtractT : State -> [128]
ExtractT [_, _, _, s3, s4] = wordsToBits [s3, s4]
Ascon_AEAD128_IV : [64]
Ascon_AEAD128_IV = 0x00001000808c0001

View File

@@ -1,56 +0,0 @@
module AsconHash where
import Ascon
// 5. Hash and eXtendable-Output Functions (XOFs)
Ascon_Digest : {n} (fin n) => [64] -> [n][64] -> [inf]
Ascon_Digest IV Ms = wordsToBits [head S | S <- iterate Ascon_p`{12} Sn]
where
S0 = Ascon_p`{12} [IV, 0, 0, 0, 0]
Sn = foldl AbsorbBlock S0 Ms
AbsorbBlock : State -> [64] -> State
AbsorbBlock [s0, s1, s2, s3, s4] X = Ascon_p`{12} [X ^ s0, s1, s2, s3, s4]
/// 5.1. Specification of Ascon-Hash256
Ascon_Hash256 : {n} (fin n) => [n] -> [256]
Ascon_Hash256 M = take (Ascon_Digest Ascon_Hash256_IV (toBlocks M))
Ascon_Hash256_IV : [64]
Ascon_Hash256_IV = 0x0000080100cc0002
Ascon_Hash256_bytes : {n} (fin n) => [n][8] -> [32][8]
Ascon_Hash256_bytes M = bitsToWords (Ascon_Hash256 (wordsToBits M))
property
initial_value_works =
Ascon_p`{12} ([Ascon_Hash256_IV] # zero)
==
[0x9b1e5494e934d681, 0x4bc3a01e333751d2, 0xae65396c6b34b81a, 0x3c7fd4a4d56a4db3, 0x1a5c464906c5976d]
// 5.2. Specification of Ascon-XOF128
Ascon_XOF128 : {r, n} (fin n, fin r) => [n] -> [r]
Ascon_XOF128 M = take (Ascon_Digest Ascon_XOF128_IV (toBlocks M))
Ascon_XOF128_IV : [64]
Ascon_XOF128_IV = 0x0000080000cc0003
Ascon_XOF128_bytes : {r, n} (fin n, fin r) => [n][8] -> [r][8]
Ascon_XOF128_bytes M = bitsToWords (Ascon_XOF128 (wordsToBits M))
// 5.3. Specification of Ascon-CXOF128
Ascon_CXOF128 : {r, c, n} (fin n, fin r, fin c, 64 >= width c) => [c] -> [n] -> [r]
Ascon_CXOF128 Z M = take (Ascon_Digest Ascon_CXOF128_IV Ms)
where
Ms = [`c]
# toBlocks Z
# toBlocks M
Ascon_CXOF128_bytes : {r, z, n} (fin n, fin r, 61 >= width z) => [z][8] -> [n][8] -> [r][8]
Ascon_CXOF128_bytes Z M = bitsToWords (Ascon_CXOF128 (wordsToBits Z) (wordsToBits M))
Ascon_CXOF128_IV : [64]
Ascon_CXOF128_IV = 0x0000080000cc0004

View File

@@ -1,11 +1,14 @@
module TestAsconAEAD128 where module TestAsconAEAD128 where
import Ascon import Ascon
import AsconCipher
testcase : {n, m} (fin m, fin n) => [128] -> [128] -> [8 * m] -> [8 * n] -> [8 * (m + 16)] -> Bit testcase : {n, m} (fin m, fin n) => [128] -> [128] -> [8 * m] -> [8 * n] -> [8 * (m + 16)] -> Bit
testcase K N P A C = testcase K N P A C =
Ascon_AEAD128_bytes (split K) (split N) (split A) (split P) == split C AEAD128_encrypt_bytes (split K) (split N) (split A) (split P) == split C
/\
case AEAD128_decrypt_bytes (split K) (split N) (split A) (split C) of
None -> False
Some p -> p == split P
property property
test1 = testcase 0x000102030405060708090A0B0C0D0E0F 0x101112131415161718191A1B1C1D1E1F [] 0x 0x4F9C278211BEC9316BF68F46EE8B2EC6 test1 = testcase 0x000102030405060708090A0B0C0D0E0F 0x101112131415161718191A1B1C1D1E1F [] 0x 0x4F9C278211BEC9316BF68F46EE8B2EC6

View File

@@ -1,9 +1,9 @@
module TestAsconCXOF128 where module TestAsconCXOF128 where
import AsconHash import Ascon
testcase : {r, z, n} (fin n, fin r, 61 >= width z) => [8*n] -> [8*z] -> [8*r] -> Bool testcase : {r, z, n} (fin n, fin r, 61 >= width z) => [8*n] -> [8*z] -> [8*r] -> Bool
testcase M Z D = Ascon_CXOF128_bytes (split Z) (split M) == split D testcase M Z D = CXOF128_bytes (split Z) (split M) == split D
property property
test1 = testcase [] [] 0x4F50159EF70BB3DAD8807E034EAEBD44C4FA2CBBC8CF1F05511AB66CDCC529905CA12083FC186AD899B270B1473DC5F7EC88D1052082DCDFE69FB75D269E7B74 test1 = testcase [] [] 0x4F50159EF70BB3DAD8807E034EAEBD44C4FA2CBBC8CF1F05511AB66CDCC529905CA12083FC186AD899B270B1473DC5F7EC88D1052082DCDFE69FB75D269E7B74

View File

@@ -1,9 +1,9 @@
module TestAsconHash256 where module TestAsconHash256 where
import AsconHash import Ascon
testcase : {n} (fin n) => [8*n] -> [256] -> Bool testcase : {n} (fin n) => [8*n] -> [256] -> Bool
testcase M D = Ascon_Hash256_bytes (split M) == split D testcase M D = Hash256_bytes (split M) == split D
property property
test1 = testcase [] 0x0B3BE5850F2F6B98CAF29F8FDEA89B64A1FA70AA249B8F839BD53BAA304D92B2 test1 = testcase [] 0x0B3BE5850F2F6B98CAF29F8FDEA89B64A1FA70AA249B8F839BD53BAA304D92B2

View File

@@ -1,9 +1,9 @@
module TestAsconXOF128 where module TestAsconXOF128 where
import AsconHash import Ascon
testcase : {r, n} (fin n, fin r) => [8*n] -> [8*r] -> Bool testcase : {r, n} (fin n, fin r) => [8*n] -> [8*r] -> Bool
testcase M D = Ascon_XOF128_bytes (split M) == split D testcase M D = XOF128_bytes (split M) == split D
property property
test1 = testcase [] 0x473D5E6164F58B39DFD84AACDB8AE42EC2D91FED33388EE0D960D9B3993295C6AD77855A5D3B13FE6AD9E6098988373AF7D0956D05A8F1665D2C67D1A3AD10FF test1 = testcase [] 0x473D5E6164F58B39DFD84AACDB8AE42EC2D91FED33388EE0D960D9B3993295C6AD77855A5D3B13FE6AD9E6098988373AF7D0956D05A8F1665D2C67D1A3AD10FF