Added sha384.fun to std library and alot of fixes. (0.16.3)
This commit is contained in:
parent
f0ed1d6761
commit
17241b2401
18 changed files with 820 additions and 314 deletions
|
|
@ -1,5 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.16)
|
||||
project(fun VERSION 0.16.2 LANGUAGES C)
|
||||
project(fun VERSION 0.16.3 LANGUAGES C)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
|
|
|||
|
|
@ -29,3 +29,26 @@ print(typeof(x)) // -> "String"
|
|||
|
||||
// Typed byte must remain numeric (uint8):
|
||||
// b = "oops" // Uncomment to see a runtime type error
|
||||
|
||||
/* Expected output:
|
||||
=== byte with hex literal and clamping ===
|
||||
255
|
||||
255
|
||||
255
|
||||
|
||||
=== for-loop reassigning a byte variable (shows clamping near the top end) ===
|
||||
250
|
||||
251
|
||||
252
|
||||
253
|
||||
254
|
||||
255
|
||||
255
|
||||
255
|
||||
255
|
||||
255
|
||||
|
||||
=== dynamic vs typed ===
|
||||
Number
|
||||
String
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -32,6 +32,16 @@ print(md5.md5_hex("6d65737361676520646967657374")) // -> f96b697d7cb7938d525a2f
|
|||
print(md5.md5_hex("6162636465666768696a6b6c6d6e6f707172737475767778797a")) // -> c3fcd3d76192e4007dfb496cca67e13b
|
||||
|
||||
// "Have Fun!"
|
||||
print(md5.md5_str("Have Fun!")) // ->
|
||||
print(md5.md5_str("Have Fun!")) // -> 852438d026c018c4307b916406f98c62
|
||||
|
||||
print("=== Done ===")
|
||||
|
||||
/* Expected output:
|
||||
=== MD5 demo (hex input) ===
|
||||
900150983cd24fb0d6963f7d28e17f72
|
||||
d41d8cd98f00b204e9800998ecf8427e
|
||||
f96b697d7cb7938d525a2f31aaf161d0
|
||||
c3fcd3d76192e4007dfb496cca67e13b
|
||||
812f2c01287af0e7c0a0b3daa381a51a
|
||||
=== Done ===
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -31,3 +31,12 @@ print(sha.sha256_hex("6d65737361676520646967657374")) // -> f7846f55cf23e14eebea
|
|||
print(sha.sha256_hex("6162636465666768696a6b6c6d6e6f707172737475767778797a")) // -> 71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73
|
||||
|
||||
print("=== Done ===")
|
||||
|
||||
/* Expected output:
|
||||
=== SHA-256 demo (hex input) ===
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
3859a4ec00dcbed7c01d4a462d18c1f4097a690a1d4d459be4e5b6f5a594ee68
|
||||
de8ff7370090823795e96e3b7fbee3cfad374492417da99d72ba55297f7e58ab
|
||||
5d3ed26c5e75585f56e664c0ebc63aa185ec606109f6374fefa42c862670d257
|
||||
=== Done ===
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -35,3 +35,14 @@ print(sha.sha256_str("6162636465666768696a6b6c6d6e6f707172737475767778797a")) //
|
|||
|
||||
print("=== Note ===")
|
||||
print("sha256_str(\"616263\") hashes the text 616263; sha256_hex(\"616263\") hashes bytes 0x61 0x62 0x63 (abc).")
|
||||
|
||||
/* Expected output:
|
||||
=== SHA-256 demo (raw string input via sha256_str) ===
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
3859a4ec00dcbed7c01d4a462d18c1f4097a690a1d4d459be4e5b6f5a594ee68
|
||||
faee5966a2c104cf2287085428a183fe58c18afdc5ff261571e8e9c4796ad635
|
||||
57aad00934af3b05086a755a1787884f2af6554dce4fc9cab02e7008d31dab44
|
||||
a863dce86b2577846b6fd399ae6c9830999b4525c50b74705998f3df852b6d25
|
||||
=== Note ===
|
||||
sha256_str("616263") hashes the text 616263; sha256_hex("616263") hashes bytes 0x61 0x62 0x63 (abc).
|
||||
*/
|
||||
|
|
|
|||
29
examples/sha384_example.fun
Executable file
29
examples/sha384_example.fun
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env fun
|
||||
|
||||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://hanez.org/project/fun/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-10-01
|
||||
*/
|
||||
|
||||
/*
|
||||
* Example: Using SHA384 from lib/crypt/sha384.fun
|
||||
*
|
||||
* Expected output for "abc":
|
||||
* cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7
|
||||
*/
|
||||
|
||||
#include <crypt/sha384.fun>
|
||||
|
||||
s = SHA384()
|
||||
|
||||
// Hex input representing "abc"
|
||||
print(s.sha384_hex("616263"))
|
||||
|
||||
// Raw string input
|
||||
print(s.sha384_str("abc"))
|
||||
|
|
@ -33,3 +33,11 @@ print(sha.sha512_hex("6d65737361676520646967657374"))
|
|||
// 3f36cc64dab6c0c5
|
||||
|
||||
print("=== Done ===")
|
||||
|
||||
/* Expected output:
|
||||
=== SHA-512 demo (hex input) ===
|
||||
cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
|
||||
ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f
|
||||
107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c
|
||||
=== Done ===
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -32,3 +32,12 @@ print(sha.sha512_str("616263")) // -> ee21095236a9c037f705f41ffa3cf60869891fcdb
|
|||
|
||||
print("=== Note ===")
|
||||
print("sha512_str(\"616263\") hashes the text 616263; sha512_hex(\"616263\") hashes bytes 0x61 0x62 0x63 (abc).")
|
||||
|
||||
/* Expected output:
|
||||
=== SHA-512 demo (raw string input via sha512_str) ===
|
||||
cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
|
||||
ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f
|
||||
ee21095236a9c037f705f41ffa3cf60869891fcdb461c5c8fe50e5b1711a27bfc02de2e387228651bdd034113cc59af777fdb9c915b70fdbed0eeacf7113296b
|
||||
=== Note ===
|
||||
sha512_str("616263") hashes the text 616263; sha512_hex("616263") hashes bytes 0x61 0x62 0x63 (abc).
|
||||
*/
|
||||
|
|
|
|||
3
lib/README.md
Normal file
3
lib/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# README
|
||||
|
||||
The Fun standard library.
|
||||
3
lib/core/README.md
Normal file
3
lib/core/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# README
|
||||
|
||||
In this directory every file should just contain one function if possible!
|
||||
62
lib/core/string_to_bytes_ascii.fun
Normal file
62
lib/core/string_to_bytes_ascii.fun
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://hanez.org/project/fun/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-10-01
|
||||
*/
|
||||
|
||||
// ASCII string to bytes (printable ASCII 0x20..0x7E)
|
||||
fun string_to_bytes_ascii(s)
|
||||
str = to_string(s)
|
||||
out = []
|
||||
number i = 0
|
||||
// ASCII printable ranges
|
||||
P1 = " !\"#$%&'()*+,-./" // 32..47
|
||||
P2 = "0123456789" // 48..57
|
||||
P3 = ":;<=>?@" // 58..64
|
||||
P4 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // 65..90
|
||||
P5 = "[\\]^_`" // 91..96
|
||||
P6 = "abcdefghijklmnopqrstuvwxyz" // 97..122
|
||||
P7 = "{|}~" // 123..126
|
||||
while true
|
||||
ch = substr(str, i, 1)
|
||||
if (typeof(ch) != "String" || ch == "")
|
||||
break
|
||||
number code = -1
|
||||
idx = find(P1, ch)
|
||||
if (idx >= 0)
|
||||
code = 32 + idx
|
||||
else
|
||||
idx = find(P2, ch)
|
||||
if (idx >= 0)
|
||||
code = 48 + idx
|
||||
else
|
||||
idx = find(P3, ch)
|
||||
if (idx >= 0)
|
||||
code = 58 + idx
|
||||
else
|
||||
idx = find(P4, ch)
|
||||
if (idx >= 0)
|
||||
code = 65 + idx
|
||||
else
|
||||
idx = find(P5, ch)
|
||||
if (idx >= 0)
|
||||
code = 91 + idx
|
||||
else
|
||||
idx = find(P6, ch)
|
||||
if (idx >= 0)
|
||||
code = 97 + idx
|
||||
else
|
||||
idx = find(P7, ch)
|
||||
if (idx >= 0)
|
||||
code = 123 + idx
|
||||
else
|
||||
// non-printable -> 0
|
||||
code = 0
|
||||
push(out, code)
|
||||
i = i + 1
|
||||
return out
|
||||
|
|
@ -18,265 +18,7 @@
|
|||
// Example:
|
||||
// print(md5_hex("616263")) // "abc" => 900150983cd24fb0d6963f7d28e17f72
|
||||
|
||||
/* Legacy global API and helpers are commented out below.
|
||||
Please use the MD5 class (see at the end of this file).
|
||||
|
||||
fun u32(x)
|
||||
// bring x into [0 .. 2^32-1] by modular reduction
|
||||
m = 4294967296
|
||||
while x < 0
|
||||
x = x + m
|
||||
while x >= m
|
||||
x = x - m
|
||||
return x
|
||||
|
||||
fun shl32(x, s)
|
||||
return shl(u32(x), s)
|
||||
|
||||
fun shr32(x, s)
|
||||
return shr(u32(x), s)
|
||||
|
||||
fun rol32(x, s)
|
||||
return rol(u32(x), s)
|
||||
|
||||
fun and32(a, b)
|
||||
return band(u32(a), u32(b))
|
||||
|
||||
fun or32(a, b)
|
||||
return bor(u32(a), u32(b))
|
||||
|
||||
fun xor32(a, b)
|
||||
return bxor(u32(a), u32(b))
|
||||
|
||||
fun not32(x)
|
||||
return bnot(u32(x))
|
||||
|
||||
fun add32(a, b)
|
||||
return u32(a + b)
|
||||
|
||||
fun add32_4(a, b, c, d)
|
||||
return u32(u32(u32(a + b) + c) + d)
|
||||
|
||||
fun hex_val(ch)
|
||||
if (ch == "0")
|
||||
return 0
|
||||
else if (ch == "1")
|
||||
return 1
|
||||
else if (ch == "2")
|
||||
return 2
|
||||
else if (ch == "3")
|
||||
return 3
|
||||
else if (ch == "4")
|
||||
return 4
|
||||
else if (ch == "5")
|
||||
return 5
|
||||
else if (ch == "6")
|
||||
return 6
|
||||
else if (ch == "7")
|
||||
return 7
|
||||
else if (ch == "8")
|
||||
return 8
|
||||
else if (ch == "9")
|
||||
return 9
|
||||
else if (ch == "a" || ch == "A")
|
||||
return 10
|
||||
else if (ch == "b" || ch == "B")
|
||||
return 11
|
||||
else if (ch == "c" || ch == "C")
|
||||
return 12
|
||||
else if (ch == "d" || ch == "D")
|
||||
return 13
|
||||
else if (ch == "e" || ch == "E")
|
||||
return 14
|
||||
else if (ch == "f" || ch == "F")
|
||||
return 15
|
||||
else
|
||||
return 0
|
||||
|
||||
fun byte_from_hex_pair(hh)
|
||||
// hh is 2-char string
|
||||
hi = hex_val(substr(hh, 0, 1))
|
||||
lo = hex_val(substr(hh, 1, 1))
|
||||
return hi * 16 + lo
|
||||
|
||||
fun from_hex(hex)
|
||||
// parse even-length hex string to array of bytes (numbers 0..255)
|
||||
arr = []
|
||||
i = 0
|
||||
n = len(hex)
|
||||
while i + 1 < n
|
||||
b = byte_from_hex_pair(substr(hex, i, 2))
|
||||
push(arr, b)
|
||||
i = i + 2
|
||||
return arr
|
||||
|
||||
fun two_hex(n)
|
||||
n = n % 256
|
||||
d = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"]
|
||||
hi = n / 16
|
||||
lo = n % 16
|
||||
// build with join
|
||||
parts = [d[hi], d[lo]]
|
||||
return join(parts, "")
|
||||
|
||||
fun bytes_to_hex(arr)
|
||||
i = 0
|
||||
out = []
|
||||
while i < len(arr)
|
||||
push(out, two_hex(arr[i]))
|
||||
i = i + 1
|
||||
return join(out, "")
|
||||
|
||||
// MD5 auxiliary functions
|
||||
fun F(x, y, z)
|
||||
return or32(and32(x, y), and32(not32(x), z))
|
||||
|
||||
fun G(x, y, z)
|
||||
return or32(and32(x, z), and32(y, not32(z)))
|
||||
|
||||
fun H(x, y, z)
|
||||
return xor32(xor32(x, y), z)
|
||||
|
||||
fun I(x, y, z)
|
||||
return xor32(y, or32(x, not32(z)))
|
||||
|
||||
// T constants (K) = floor(abs(sin(i+1)) * 2^32), i=0..63
|
||||
K = [
|
||||
3614090360, 3905402710, 606105819, 3250441966, 4118548399, 1200080426, 2821735955, 4249261313,
|
||||
1770035416, 2336552879, 4294925233, 2304563134, 1804603682, 4254626195, 2792965006, 1236535329,
|
||||
4129170786, 3225465664, 643717713, 3921069994, 3593408605, 38016083, 3634488961, 3889429448,
|
||||
568446438, 3275163606, 4107603335, 1163531501, 2850285829, 4243563512, 1735328473, 2368359562,
|
||||
4294588738, 2272392833, 1839030562, 4259657740, 2763975236, 1272893353, 4139469664, 3200236656,
|
||||
681279174, 3936430074, 3572445317, 76029189, 3654602809, 3873151461, 530742520, 3299628645,
|
||||
4096336452, 1126891415, 2878612391, 4237533241, 1700485571, 2399980690, 4293915773, 2240044497,
|
||||
1873313359, 4264355552, 2734768916, 1309151649, 4149444226, 3174756917, 718787259, 3951481745
|
||||
]
|
||||
|
||||
// per-round rotation amounts
|
||||
S = [
|
||||
7,12,17,22, 7,12,17,22, 7,12,17,22, 7,12,17,22,
|
||||
5, 9,14,20, 5, 9,14,20, 5, 9,14,20, 5, 9,14,20,
|
||||
4,11,16,23, 4,11,16,23, 4,11,16,23, 4,11,16,23,
|
||||
6,10,15,21, 6,10,15,21, 6,10,15,21, 6,10,15,21
|
||||
]
|
||||
|
||||
fun pad_bytes(bytes)
|
||||
// returns a new array with MD5 padding
|
||||
L = len(bytes)
|
||||
out = []
|
||||
// copy original bytes
|
||||
i = 0
|
||||
while i < L
|
||||
push(out, bytes[i])
|
||||
i = i + 1
|
||||
// append 0x80
|
||||
push(out, 128)
|
||||
// pad zeros until length % 64 == 56
|
||||
while (len(out) % 64) != 56
|
||||
push(out, 0)
|
||||
// append length (bits) as 64-bit little-endian
|
||||
len_bits = L * 8
|
||||
j = 0
|
||||
while j < 8
|
||||
b = (len_bits / pow(2, 8 * j)) % 256
|
||||
push(out, b)
|
||||
j = j + 1
|
||||
return out
|
||||
|
||||
fun word32_le(b0, b1, b2, b3)
|
||||
return u32(b0 + b1 * 256 + b2 * 65536 + b3 * 16777216)
|
||||
|
||||
fun process_block(state, block)
|
||||
// state: [a0,b0,c0,d0], block: 64 bytes array
|
||||
a0 = state[0]
|
||||
b0 = state[1]
|
||||
c0 = state[2]
|
||||
d0 = state[3]
|
||||
|
||||
// M[16] little-endian words
|
||||
M = []
|
||||
i = 0
|
||||
while i < 16
|
||||
j = i * 4
|
||||
w = word32_le(block[j], block[j+1], block[j+2], block[j+3])
|
||||
push(M, w)
|
||||
i = i + 1
|
||||
|
||||
A = a0
|
||||
B = b0
|
||||
C = c0
|
||||
D = d0
|
||||
|
||||
k = 0
|
||||
while k < 64
|
||||
if (k < 16)
|
||||
f = F(B, C, D)
|
||||
g = k
|
||||
else if (k < 32)
|
||||
f = G(B, C, D)
|
||||
g = (5 * k + 1) % 16
|
||||
else if (k < 48)
|
||||
f = H(B, C, D)
|
||||
g = (3 * k + 5) % 16
|
||||
else
|
||||
f = I(B, C, D)
|
||||
g = (7 * k) % 16
|
||||
|
||||
tmp = D
|
||||
sum = add32_4(A, f, K[k], M[g])
|
||||
D = C
|
||||
C = B
|
||||
B = add32(B, rol32(sum, S[k]))
|
||||
A = tmp
|
||||
k = k + 1
|
||||
|
||||
state[0] = add32(state[0], A)
|
||||
state[1] = add32(state[1], B)
|
||||
state[2] = add32(state[2], C)
|
||||
state[3] = add32(state[3], D)
|
||||
return state
|
||||
|
||||
fun md5_bytes(bytes)
|
||||
// returns array of 16 bytes of digest
|
||||
data = pad_bytes(bytes)
|
||||
// initial state
|
||||
a0 = 1732584193 // 0x67452301
|
||||
b0 = 4023233417 // 0xEFCDAB89
|
||||
c0 = 2562383102 // 0x98BADCFE
|
||||
d0 = 271733878 // 0x10325476
|
||||
state = [a0, b0, c0, d0]
|
||||
|
||||
off = 0
|
||||
N = len(data)
|
||||
while off < N
|
||||
block = []
|
||||
i = 0
|
||||
while i < 64
|
||||
push(block, data[off + i])
|
||||
i = i + 1
|
||||
state = process_block(state, block)
|
||||
off = off + 64
|
||||
|
||||
// output digest as little-endian bytes of A,B,C,D
|
||||
out = []
|
||||
j = 0
|
||||
while j < 4
|
||||
v = state[j]
|
||||
// 4 bytes little-endian
|
||||
push(out, (v ) % 256)
|
||||
push(out, (v / 256) % 256)
|
||||
push(out, (v / 65536) % 256)
|
||||
push(out, (v / 16777216) % 256)
|
||||
j = j + 1
|
||||
return out
|
||||
|
||||
fun md5_hex(hexStr)
|
||||
bytes = from_hex(hexStr)
|
||||
digest = md5_bytes(bytes)
|
||||
return bytes_to_hex(digest)
|
||||
|
||||
// Class wrapper to avoid global name collisions and show class usage
|
||||
*/
|
||||
|
||||
#include <strings.fun>
|
||||
|
||||
|
|
|
|||
272
lib/crypt/md5_legacy.fun
Normal file
272
lib/crypt/md5_legacy.fun
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://hanez.org/project/fun/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-10-01
|
||||
*/
|
||||
|
||||
#include <strings.fun>
|
||||
|
||||
// Legacy global API and helpers. Please use the MD5 class (see lib/crypt/md5.fun).
|
||||
fun u32(x)
|
||||
// bring x into [0 .. 2^32-1] by modular reduction
|
||||
m = 4294967296
|
||||
while x < 0
|
||||
x = x + m
|
||||
while x >= m
|
||||
x = x - m
|
||||
return x
|
||||
|
||||
fun shl32(x, s)
|
||||
return shl(u32(x), s)
|
||||
|
||||
fun shr32(x, s)
|
||||
return shr(u32(x), s)
|
||||
|
||||
fun rol32(x, s)
|
||||
return rol(u32(x), s)
|
||||
|
||||
fun and32(a, b)
|
||||
return band(u32(a), u32(b))
|
||||
|
||||
fun or32(a, b)
|
||||
return bor(u32(a), u32(b))
|
||||
|
||||
fun xor32(a, b)
|
||||
return bxor(u32(a), u32(b))
|
||||
|
||||
fun not32(x)
|
||||
return bnot(u32(x))
|
||||
|
||||
fun add32(a, b)
|
||||
return u32(a + b)
|
||||
|
||||
fun add32_4(a, b, c, d)
|
||||
return u32(u32(u32(a + b) + c) + d)
|
||||
|
||||
fun hex_val(ch)
|
||||
if (ch == "0")
|
||||
return 0
|
||||
else if (ch == "1")
|
||||
return 1
|
||||
else if (ch == "2")
|
||||
return 2
|
||||
else if (ch == "3")
|
||||
return 3
|
||||
else if (ch == "4")
|
||||
return 4
|
||||
else if (ch == "5")
|
||||
return 5
|
||||
else if (ch == "6")
|
||||
return 6
|
||||
else if (ch == "7")
|
||||
return 7
|
||||
else if (ch == "8")
|
||||
return 8
|
||||
else if (ch == "9")
|
||||
return 9
|
||||
else if (ch == "a" || ch == "A")
|
||||
return 10
|
||||
else if (ch == "b" || ch == "B")
|
||||
return 11
|
||||
else if (ch == "c" || ch == "C")
|
||||
return 12
|
||||
else if (ch == "d" || ch == "D")
|
||||
return 13
|
||||
else if (ch == "e" || ch == "E")
|
||||
return 14
|
||||
else if (ch == "f" || ch == "F")
|
||||
return 15
|
||||
else
|
||||
return 0
|
||||
|
||||
fun byte_from_hex_pair(hh)
|
||||
// hh is 2-char string
|
||||
hi = hex_val(substr(hh, 0, 1))
|
||||
lo = hex_val(substr(hh, 1, 1))
|
||||
return hi * 16 + lo
|
||||
|
||||
fun from_hex(hex)
|
||||
// parse even-length hex string to array of bytes (numbers 0..255)
|
||||
arr = []
|
||||
i = 0
|
||||
n = len(hex)
|
||||
while i + 1 < n
|
||||
b = byte_from_hex_pair(substr(hex, i, 2))
|
||||
push(arr, b)
|
||||
i = i + 2
|
||||
return arr
|
||||
|
||||
fun two_hex(n)
|
||||
n = n % 256
|
||||
d = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"]
|
||||
hi = n / 16
|
||||
lo = n % 16
|
||||
// build with join
|
||||
parts = [d[hi], d[lo]]
|
||||
return join(parts, "")
|
||||
|
||||
fun bytes_to_hex(arr)
|
||||
i = 0
|
||||
out = []
|
||||
while i < len(arr)
|
||||
push(out, two_hex(arr[i]))
|
||||
i = i + 1
|
||||
return join(out, "")
|
||||
|
||||
// MD5 auxiliary functions
|
||||
fun F(x, y, z)
|
||||
return or32(and32(x, y), and32(not32(x), z))
|
||||
|
||||
fun G(x, y, z)
|
||||
return or32(and32(x, z), and32(y, not32(z)))
|
||||
|
||||
fun H(x, y, z)
|
||||
return xor32(xor32(x, y), z)
|
||||
|
||||
fun I(x, y, z)
|
||||
return xor32(y, or32(x, not32(z)))
|
||||
|
||||
// T constants (K) = floor(abs(sin(i+1)) * 2^32), i=0..63
|
||||
K = [
|
||||
3614090360, 3905402710, 606105819, 3250441966, 4118548399, 1200080426, 2821735955, 4249261313,
|
||||
1770035416, 2336552879, 4294925233, 2304563134, 1804603682, 4254626195, 2792965006, 1236535329,
|
||||
4129170786, 3225465664, 643717713, 3921069994, 3593408605, 38016083, 3634488961, 3889429448,
|
||||
568446438, 3275163606, 4107603335, 1163531501, 2850285829, 4243563512, 1735328473, 2368359562,
|
||||
4294588738, 2272392833, 1839030562, 4259657740, 2763975236, 1272893353, 4139469664, 3200236656,
|
||||
681279174, 3936430074, 3572445317, 76029189, 3654602809, 3873151461, 530742520, 3299628645,
|
||||
4096336452, 1126891415, 2878612391, 4237533241, 1700485571, 2399980690, 4293915773, 2240044497,
|
||||
1873313359, 4264355552, 2734768916, 1309151649, 4149444226, 3174756917, 718787259, 3951481745
|
||||
]
|
||||
|
||||
// per-round rotation amounts
|
||||
S = [
|
||||
7,12,17,22, 7,12,17,22, 7,12,17,22, 7,12,17,22,
|
||||
5, 9,14,20, 5, 9,14,20, 5, 9,14,20, 5, 9,14,20,
|
||||
4,11,16,23, 4,11,16,23, 4,11,16,23, 4,11,16,23,
|
||||
6,10,15,21, 6,10,15,21, 6,10,15,21, 6,10,15,21
|
||||
]
|
||||
|
||||
fun pad_bytes(bytes)
|
||||
// returns a new array with MD5 padding
|
||||
L = len(bytes)
|
||||
out = []
|
||||
// copy original bytes
|
||||
i = 0
|
||||
while i < L
|
||||
push(out, bytes[i])
|
||||
i = i + 1
|
||||
// append 0x80
|
||||
push(out, 128)
|
||||
// pad zeros until length % 64 == 56
|
||||
while (len(out) % 64) != 56
|
||||
push(out, 0)
|
||||
// append length (bits) as 64-bit little-endian
|
||||
len_bits = L * 8
|
||||
j = 0
|
||||
while j < 8
|
||||
b = (len_bits / pow(2, 8 * j)) % 256
|
||||
push(out, b)
|
||||
j = j + 1
|
||||
return out
|
||||
|
||||
fun word32_le(b0, b1, b2, b3)
|
||||
return u32(b0 + b1 * 256 + b2 * 65536 + b3 * 16777216)
|
||||
|
||||
fun process_block(state, block)
|
||||
// state: [a0,b0,c0,d0], block: 64 bytes array
|
||||
a0 = state[0]
|
||||
b0 = state[1]
|
||||
c0 = state[2]
|
||||
d0 = state[3]
|
||||
|
||||
// M[16] little-endian words
|
||||
M = []
|
||||
i = 0
|
||||
while i < 16
|
||||
j = i * 4
|
||||
w = word32_le(block[j], block[j+1], block[j+2], block[j+3])
|
||||
push(M, w)
|
||||
i = i + 1
|
||||
|
||||
A = a0
|
||||
B = b0
|
||||
C = c0
|
||||
D = d0
|
||||
|
||||
k = 0
|
||||
while k < 64
|
||||
if (k < 16)
|
||||
f = F(B, C, D)
|
||||
g = k
|
||||
else if (k < 32)
|
||||
f = G(B, C, D)
|
||||
g = (5 * k + 1) % 16
|
||||
else if (k < 48)
|
||||
f = H(B, C, D)
|
||||
g = (3 * k + 5) % 16
|
||||
else
|
||||
f = I(B, C, D)
|
||||
g = (7 * k) % 16
|
||||
|
||||
tmp = D
|
||||
sum = add32_4(A, f, K[k], M[g])
|
||||
D = C
|
||||
C = B
|
||||
B = add32(B, rol32(sum, S[k]))
|
||||
A = tmp
|
||||
k = k + 1
|
||||
|
||||
state[0] = add32(state[0], A)
|
||||
state[1] = add32(state[1], B)
|
||||
state[2] = add32(state[2], C)
|
||||
state[3] = add32(state[3], D)
|
||||
return state
|
||||
|
||||
fun md5_bytes(bytes)
|
||||
// returns array of 16 bytes of digest
|
||||
data = pad_bytes(bytes)
|
||||
// initial state
|
||||
a0 = 1732584193 // 0x67452301
|
||||
b0 = 4023233417 // 0xEFCDAB89
|
||||
c0 = 2562383102 // 0x98BADCFE
|
||||
d0 = 271733878 // 0x10325476
|
||||
state = [a0, b0, c0, d0]
|
||||
|
||||
off = 0
|
||||
N = len(data)
|
||||
while off < N
|
||||
block = []
|
||||
i = 0
|
||||
while i < 64
|
||||
push(block, data[off + i])
|
||||
i = i + 1
|
||||
state = process_block(state, block)
|
||||
off = off + 64
|
||||
|
||||
// output digest as little-endian bytes of A,B,C,D
|
||||
out = []
|
||||
j = 0
|
||||
while j < 4
|
||||
v = state[j]
|
||||
// 4 bytes little-endian
|
||||
push(out, (v) % 256)
|
||||
push(out, (v / 256) % 256)
|
||||
push(out, (v / 65536) % 256)
|
||||
push(out, (v / 16777216) % 256)
|
||||
j = j + 1
|
||||
return out
|
||||
|
||||
fun md5_hex(hexStr)
|
||||
bytes = from_hex(hexStr)
|
||||
digest = md5_bytes(bytes)
|
||||
return bytes_to_hex(digest)
|
||||
|
||||
fun md5_str(this, str)
|
||||
bytes = string_to_bytes_ascii(str)
|
||||
digest = this.md5_bytes(bytes)
|
||||
return this.bytes_to_hex(digest)
|
||||
368
lib/crypt/sha384.fun
Normal file
368
lib/crypt/sha384.fun
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://hanez.org/project/fun/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the Apache-2.0 license.
|
||||
* https://opensource.org/license/apache-2-0
|
||||
*
|
||||
* Added: 2025-10-01
|
||||
*/
|
||||
|
||||
// lib/crypt/sha384.fun
|
||||
// Pure Fun SHA-384 implementation operating on hex-string input.
|
||||
// 64-bit words are represented as [hi, lo] (two uint32 parts).
|
||||
//
|
||||
// Public API (class):
|
||||
// s = SHA384()
|
||||
// s.sha384_hex(hexStr) -> digest hex string (lowercase, 96 hex chars)
|
||||
// s.sha384_str(str) -> digest hex string (lowercase, 96 hex chars)
|
||||
//
|
||||
// Known test vector ("abc"):
|
||||
// SHA-384("abc") =
|
||||
// cb00753f45a35e8bb5a03d699ac65007272c32ab0eded163
|
||||
// 1a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7
|
||||
|
||||
#include <strings.fun>
|
||||
|
||||
class SHA384()
|
||||
// -------- hex helpers --------
|
||||
fun hex_val(this, ch)
|
||||
if (ch == "0")
|
||||
return 0
|
||||
else if (ch == "1")
|
||||
return 1
|
||||
else if (ch == "2")
|
||||
return 2
|
||||
else if (ch == "3")
|
||||
return 3
|
||||
else if (ch == "4")
|
||||
return 4
|
||||
else if (ch == "5")
|
||||
return 5
|
||||
else if (ch == "6")
|
||||
return 6
|
||||
else if (ch == "7")
|
||||
return 7
|
||||
else if (ch == "8")
|
||||
return 8
|
||||
else if (ch == "9")
|
||||
return 9
|
||||
else if (ch == "a" || ch == "A")
|
||||
return 10
|
||||
else if (ch == "b" || ch == "B")
|
||||
return 11
|
||||
else if (ch == "c" || ch == "C")
|
||||
return 12
|
||||
else if (ch == "d" || ch == "D")
|
||||
return 13
|
||||
else if (ch == "e" || ch == "E")
|
||||
return 14
|
||||
else if (ch == "f" || ch == "F")
|
||||
return 15
|
||||
else
|
||||
return 0
|
||||
|
||||
fun byte_from_hex_pair(this, hh)
|
||||
number hi = this.hex_val(substr(hh, 0, 1))
|
||||
number lo = this.hex_val(substr(hh, 1, 1))
|
||||
return hi * 16 + lo
|
||||
|
||||
fun from_hex(this, hex)
|
||||
hex = to_string(hex)
|
||||
arr = []
|
||||
number i = 0
|
||||
number n = len(hex)
|
||||
while i + 1 < n
|
||||
number b = this.byte_from_hex_pair(substr(hex, i, 2))
|
||||
push(arr, b)
|
||||
i = i + 2
|
||||
return arr
|
||||
|
||||
fun two_hex(this, n)
|
||||
n = n % 256
|
||||
hexd = "0123456789abcdef"
|
||||
number hi = (n / 16) % 16
|
||||
number lo = n % 16
|
||||
c1 = substr(hexd, hi, 1)
|
||||
c2 = substr(hexd, lo, 1)
|
||||
return join([c1, c2], "")
|
||||
|
||||
fun bytes_to_hex(this, arr)
|
||||
out = []
|
||||
number i = 0
|
||||
number L = len(arr)
|
||||
while i < L
|
||||
push(out, this.two_hex(arr[i]))
|
||||
i = i + 1
|
||||
return join(out, "")
|
||||
|
||||
// -------- 32/64 helpers --------
|
||||
fun u32(this, x)
|
||||
m = 4294967296
|
||||
while x < 0
|
||||
x = x + m
|
||||
while x >= m
|
||||
x = x - m
|
||||
return x
|
||||
|
||||
// 64-bit as [hi, lo] (each uint32)
|
||||
fun pack64_be(this, b0,b1,b2,b3,b4,b5,b6,b7)
|
||||
number hi = this.u32(b0 * 16777216 + b1 * 65536 + b2 * 256 + b3)
|
||||
number lo = this.u32(b4 * 16777216 + b5 * 65536 + b6 * 256 + b7)
|
||||
return [hi, lo]
|
||||
|
||||
fun add64(this, a, b)
|
||||
number alo = this.u32(a[1])
|
||||
number ahi = this.u32(a[0])
|
||||
number blo = this.u32(b[1])
|
||||
number bhi = this.u32(b[0])
|
||||
number sum_lo = alo + blo
|
||||
number carry = sum_lo / 4294967296
|
||||
sum_lo = sum_lo % 4294967296
|
||||
number sum_hi = (ahi + bhi + carry) % 4294967296
|
||||
return [sum_hi, sum_lo]
|
||||
|
||||
fun add64_5(this, a, b, c, d, e)
|
||||
return this.add64(this.add64(this.add64(this.add64(a, b), c), d), e)
|
||||
|
||||
fun xor64(this, a, b)
|
||||
return [ bxor(a[0], b[0]), bxor(a[1], b[1]) ]
|
||||
|
||||
fun and64(this, a, b)
|
||||
return [ band(a[0], b[0]), band(a[1], b[1]) ]
|
||||
|
||||
fun or64(this, a, b)
|
||||
return [ bor(a[0], b[0]), bor(a[1], b[1]) ]
|
||||
|
||||
fun not64(this, a)
|
||||
return [ bnot(a[0]), bnot(a[1]) ]
|
||||
|
||||
// logical right shift by n (0..63)
|
||||
fun shr64(this, a, n)
|
||||
number s = n % 64
|
||||
number hi = a[0]
|
||||
number lo = a[1]
|
||||
if (s == 0)
|
||||
return [hi, lo]
|
||||
else if (s < 32)
|
||||
number new_lo = bor( shr(lo, s), shl(hi, 32 - s) )
|
||||
number new_hi = shr(hi, s)
|
||||
return [ new_hi, new_lo ]
|
||||
else
|
||||
number k = s - 32
|
||||
number new_lo2 = shr(hi, k)
|
||||
return [ 0, new_lo2 ]
|
||||
|
||||
// rotate right by n (0..63)
|
||||
fun rotr64(this, a, n)
|
||||
number s = n % 64
|
||||
number hi = a[0]
|
||||
number lo = a[1]
|
||||
if (s == 0)
|
||||
return [hi, lo]
|
||||
else if (s < 32)
|
||||
number new_lo = bor( shr(lo, s), shl(hi, 32 - s) )
|
||||
number new_hi = bor( shr(hi, s), shl(lo, 32 - s) )
|
||||
return [ new_hi, new_lo ]
|
||||
else
|
||||
number k = s - 32
|
||||
// swap roles
|
||||
number new_lo2 = bor( shr(hi, k), shl(lo, 32 - k) )
|
||||
number new_hi2 = bor( shr(lo, k), shl(hi, 32 - k) )
|
||||
return [ new_hi2, new_lo2 ]
|
||||
|
||||
// SHA-512 logical functions (used by SHA-384 rounds)
|
||||
fun Ch(this, x, y, z)
|
||||
// (x & y) ^ (~x & z)
|
||||
return this.xor64(this.and64(x, y), this.and64(this.not64(x), z))
|
||||
|
||||
fun Maj(this, x, y, z)
|
||||
// (x & y) ^ (x & z) ^ (y & z)
|
||||
return this.xor64(this.xor64(this.and64(x, y), this.and64(x, z)), this.and64(y, z))
|
||||
|
||||
fun Sigma0(this, x)
|
||||
return this.xor64(this.xor64(this.rotr64(x, 28), this.rotr64(x, 34)), this.rotr64(x, 39))
|
||||
|
||||
fun Sigma1(this, x)
|
||||
return this.xor64(this.xor64(this.rotr64(x, 14), this.rotr64(x, 18)), this.rotr64(x, 41))
|
||||
|
||||
fun sigma0(this, x)
|
||||
return this.xor64(this.xor64(this.rotr64(x, 1), this.rotr64(x, 8)), this.shr64(x, 7))
|
||||
|
||||
fun sigma1(this, x)
|
||||
return this.xor64(this.xor64(this.rotr64(x, 19), this.rotr64(x, 61)), this.shr64(x, 6))
|
||||
|
||||
// -------- constants --------
|
||||
// SHA-384 uses the same K constants as SHA-512
|
||||
K = [
|
||||
[0x428a2f98,0xd728ae22],[0x71374491,0x23ef65cd],[0xb5c0fbcf,0xec4d3b2f],[0xe9b5dba5,0x8189dbbc],
|
||||
[0x3956c25b,0xf348b538],[0x59f111f1,0xb605d019],[0x923f82a4,0xaf194f9b],[0xab1c5ed5,0xda6d8118],
|
||||
[0xd807aa98,0xa3030242],[0x12835b01,0x45706fbe],[0x243185be,0x4ee4b28c],[0x550c7dc3,0xd5ffb4e2],
|
||||
[0x72be5d74,0xf27b896f],[0x80deb1fe,0x3b1696b1],[0x9bdc06a7,0x25c71235],[0xc19bf174,0xcf692694],
|
||||
[0xe49b69c1,0x9ef14ad2],[0xefbe4786,0x384f25e3],[0x0fc19dc6,0x8b8cd5b5],[0x240ca1cc,0x77ac9c65],
|
||||
[0x2de92c6f,0x592b0275],[0x4a7484aa,0x6ea6e483],[0x5cb0a9dc,0xbd41fbd4],[0x76f988da,0x831153b5],
|
||||
[0x983e5152,0xee66dfab],[0xa831c66d,0x2db43210],[0xb00327c8,0x98fb213f],[0xbf597fc7,0xbeef0ee4],
|
||||
[0xc6e00bf3,0x3da88fc2],[0xd5a79147,0x930aa725],[0x06ca6351,0xe003826f],[0x14292967,0x0a0e6e70],
|
||||
[0x27b70a85,0x46d22ffc],[0x2e1b2138,0x5c26c926],[0x4d2c6dfc,0x5ac42aed],[0x53380d13,0x9d95b3df],
|
||||
[0x650a7354,0x8baf63de],[0x766a0abb,0x3c77b2a8],[0x81c2c92e,0x47edaee6],[0x92722c85,0x1482353b],
|
||||
[0xa2bfe8a1,0x4cf10364],[0xa81a664b,0xbc423001],[0xc24b8b70,0xd0f89791],[0xc76c51a3,0x0654be30],
|
||||
[0xd192e819,0xd6ef5218],[0xd6990624,0x5565a910],[0xf40e3585,0x5771202a],[0x106aa070,0x32bbd1b8],
|
||||
[0x19a4c116,0xb8d2d0c8],[0x1e376c08,0x5141ab53],[0x2748774c,0xdf8eeb99],[0x34b0bcb5,0xe19b48a8],
|
||||
[0x391c0cb3,0xc5c95a63],[0x4ed8aa4a,0xe3418acb],[0x5b9cca4f,0x7763e373],[0x682e6ff3,0xd6b2b8a3],
|
||||
[0x748f82ee,0x5defb2fc],[0x78a5636f,0x43172f60],[0x84c87814,0xa1f0ab72],[0x8cc70208,0x1a6439ec],
|
||||
[0x90befffa,0x23631e28],[0xa4506ceb,0xde82bde9],[0xbef9a3f7,0xb2c67915],[0xc67178f2,0xe372532b],
|
||||
[0xca273ece,0xea26619c],[0xd186b8c7,0x21c0c207],[0xeada7dd6,0xcde0eb1e],[0xf57d4f7f,0xee6ed178],
|
||||
[0x06f067aa,0x72176fba],[0x0a637dc5,0xa2c898a6],[0x113f9804,0xbef90dae],[0x1b710b35,0x131c471b],
|
||||
[0x28db77f5,0x23047d84],[0x32caab7b,0x40c72493],[0x3c9ebe0a,0x15c9bebc],[0x431d67c4,0x9c100d4c],
|
||||
[0x4cc5d4be,0xcb3e42b6],[0x597f299c,0xfc657e2a],[0x5fcb6fab,0x3ad6faec],[0x6c44198c,0x4a475817]
|
||||
]
|
||||
|
||||
// SHA-384 initial hash value (IV), 64-bit words split into [hi, lo]
|
||||
IV = [
|
||||
[0xcbbb9d5d, 0xc1059ed8], [0x629a292a, 0x367cd507], [0x9159015a, 0x3070dd17], [0x152fecd8, 0xf70e5939],
|
||||
[0x67332667, 0xffc00b31], [0x8eb44a87, 0x68581511], [0xdb0c2e0d, 0x64f98fa7], [0x47b5481d, 0xbefa4fa4]
|
||||
]
|
||||
|
||||
// -------- padding --------
|
||||
fun pad_bytes(this, bytes)
|
||||
number L = len(bytes)
|
||||
out = []
|
||||
// copy bytes
|
||||
number i = 0
|
||||
while i < L
|
||||
push(out, bytes[i])
|
||||
i = i + 1
|
||||
// append 0x80
|
||||
push(out, 128)
|
||||
// pad zeros until length % 128 == 112 (i.e., 896 bits)
|
||||
while (len(out) % 128) != 112
|
||||
push(out, 0)
|
||||
// append 128-bit length (we use upper 64 bits zero, lower 64 = L*8)
|
||||
number j = 0
|
||||
while j < 8
|
||||
push(out, 0)
|
||||
j = j + 1
|
||||
// lower 8 bytes big-endian
|
||||
number bits = L * 8
|
||||
number t = 7
|
||||
while t >= 0
|
||||
number b = (bits / pow(2, 8 * t)) % 256
|
||||
push(out, b)
|
||||
t = t - 1
|
||||
return out
|
||||
|
||||
// -------- core --------
|
||||
fun process_block(this, H, block)
|
||||
// W ring buffer of 16 words ([hi, lo])
|
||||
W = []
|
||||
number i = 0
|
||||
while i < 16
|
||||
number j = i * 8
|
||||
push(W, this.pack64_be(block[j],block[j+1],block[j+2],block[j+3],
|
||||
block[j+4],block[j+5],block[j+6],block[j+7]))
|
||||
i = i + 1
|
||||
|
||||
a = H[0]
|
||||
b = H[1]
|
||||
c = H[2]
|
||||
d = H[3]
|
||||
e = H[4]
|
||||
f = H[5]
|
||||
g = H[6]
|
||||
h = H[7]
|
||||
|
||||
number t = 0
|
||||
while t < 80
|
||||
number idx = t % 16
|
||||
if (t >= 16)
|
||||
w2 = W[(t - 2) % 16]
|
||||
w7 = W[(t - 7) % 16]
|
||||
w15 = W[(t - 15) % 16]
|
||||
w16 = W[(t - 16) % 16]
|
||||
s1 = this.sigma1(w2)
|
||||
s0 = this.sigma0(w15)
|
||||
tmp = this.add64(w16, s0)
|
||||
tmp = this.add64(tmp, w7)
|
||||
W[idx] = this.add64(tmp, s1)
|
||||
Wt = W[idx]
|
||||
|
||||
// Precompute hot terms once per round
|
||||
Se1 = this.Sigma1(e)
|
||||
ch = this.Ch(e, f, g)
|
||||
|
||||
// T1 = h + Se1 + ch + K[t] + Wt
|
||||
tmp1 = this.add64(h, Se1)
|
||||
tmp1 = this.add64(tmp1, ch)
|
||||
tmp1 = this.add64(tmp1, this.K[t])
|
||||
T1 = this.add64(tmp1, Wt)
|
||||
|
||||
// T2 = Sigma0(a) + Maj(a, b, c)
|
||||
T2 = this.add64(this.Sigma0(a), this.Maj(a, b, c))
|
||||
|
||||
// State update
|
||||
h = g
|
||||
g = f
|
||||
f = e
|
||||
e = this.add64(d, T1)
|
||||
d = c
|
||||
c = b
|
||||
b = a
|
||||
a = this.add64(T1, T2)
|
||||
t = t + 1
|
||||
|
||||
H[0] = this.add64(H[0], a)
|
||||
H[1] = this.add64(H[1], b)
|
||||
H[2] = this.add64(H[2], c)
|
||||
H[3] = this.add64(H[3], d)
|
||||
H[4] = this.add64(H[4], e)
|
||||
H[5] = this.add64(H[5], f)
|
||||
H[6] = this.add64(H[6], g)
|
||||
H[7] = this.add64(H[7], h)
|
||||
return H
|
||||
|
||||
fun sha384_bytes(this, bytes)
|
||||
data = this.pad_bytes(bytes)
|
||||
// init H (deep copy IV)
|
||||
H = [ this.IV[0], this.IV[1], this.IV[2], this.IV[3], this.IV[4], this.IV[5], this.IV[6], this.IV[7] ]
|
||||
number off = 0
|
||||
number N = len(data)
|
||||
while off < N
|
||||
block = []
|
||||
number i = 0
|
||||
while i < 128
|
||||
push(block, data[off + i])
|
||||
i = i + 1
|
||||
H = this.process_block(H, block)
|
||||
off = off + 128
|
||||
|
||||
// output 48 bytes big-endian from H[0..5]
|
||||
out = []
|
||||
number j = 0
|
||||
while j < 6
|
||||
word = H[j]
|
||||
number hi = word[0]
|
||||
number lo = word[1]
|
||||
// hi
|
||||
push(out, (hi / 16777216) % 256)
|
||||
push(out, (hi / 65536) % 256)
|
||||
push(out, (hi / 256) % 256)
|
||||
push(out, hi % 256)
|
||||
// lo
|
||||
push(out, (lo / 16777216) % 256)
|
||||
push(out, (lo / 65536) % 256)
|
||||
push(out, (lo / 256) % 256)
|
||||
push(out, lo % 256)
|
||||
j = j + 1
|
||||
return out
|
||||
|
||||
fun sha384_hex(this, hexStr)
|
||||
bytes = this.from_hex(hexStr)
|
||||
digest = this.sha384_bytes(bytes)
|
||||
return this.bytes_to_hex(digest)
|
||||
|
||||
// Hash raw string bytes (printable ASCII)
|
||||
fun sha384_str(this, str)
|
||||
bytes = string_to_bytes_ascii(str)
|
||||
digest = this.sha384_bytes(bytes)
|
||||
return this.bytes_to_hex(digest)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://hanez.org/project/fun/
|
||||
*
|
||||
|
|
@ -9,54 +9,7 @@
|
|||
* Added: 2025-10-01
|
||||
*/
|
||||
|
||||
// ASCII string to bytes (printable ASCII 0x20..0x7E)
|
||||
fun string_to_bytes_ascii(this, s)
|
||||
str = to_string(s)
|
||||
out = []
|
||||
number i = 0
|
||||
// ASCII printable ranges
|
||||
P1 = " !\"#$%&'()*+,-./" // 32..47
|
||||
P2 = "0123456789" // 48..57
|
||||
P3 = ":;<=>?@" // 58..64
|
||||
P4 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // 65..90
|
||||
P5 = "[\\]^_`" // 91..96
|
||||
P6 = "abcdefghijklmnopqrstuvwxyz" // 97..122
|
||||
P7 = "{|}~" // 123..126
|
||||
while true
|
||||
ch = substr(str, i, 1)
|
||||
if (typeof(ch) != "String" || ch == "")
|
||||
break
|
||||
number code = -1
|
||||
idx = find(P1, ch)
|
||||
if (idx >= 0)
|
||||
code = 32 + idx
|
||||
else
|
||||
idx = find(P2, ch)
|
||||
if (idx >= 0)
|
||||
code = 48 + idx
|
||||
else
|
||||
idx = find(P3, ch)
|
||||
if (idx >= 0)
|
||||
code = 58 + idx
|
||||
else
|
||||
idx = find(P4, ch)
|
||||
if (idx >= 0)
|
||||
code = 65 + idx
|
||||
else
|
||||
idx = find(P5, ch)
|
||||
if (idx >= 0)
|
||||
code = 91 + idx
|
||||
else
|
||||
idx = find(P6, ch)
|
||||
if (idx >= 0)
|
||||
code = 97 + idx
|
||||
else
|
||||
idx = find(P7, ch)
|
||||
if (idx >= 0)
|
||||
code = 123 + idx
|
||||
else
|
||||
// non-printable -> 0
|
||||
code = 0
|
||||
push(out, code)
|
||||
i = i + 1
|
||||
return out
|
||||
// This file should not contain code! It should just include all string related
|
||||
// functions from core/*.fun.
|
||||
|
||||
#include <core/string_to_bytes_ascii.fun>
|
||||
|
|
|
|||
4
play.fun
4
play.fun
|
|
@ -9,6 +9,8 @@
|
|||
* https://opensource.org/license/apache-2-0
|
||||
*/
|
||||
|
||||
include <strings.fun>
|
||||
|
||||
fun foo()
|
||||
print("Have fun!")
|
||||
print("Having fun... forever.")
|
||||
|
|
@ -17,6 +19,8 @@ print("Typeof foo(): " + typeof(foo))
|
|||
|
||||
print("Yay, the playground for having fun... ;)")
|
||||
|
||||
print(string_to_bytes_ascii("Have Fun!"))
|
||||
|
||||
number n = 23
|
||||
// Every type MUST be lowercase. Sint* must be sint*.
|
||||
print(n)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
* // Stack after: [5]
|
||||
*
|
||||
* @author Johannes Findeisen
|
||||
* @date 2025-10-16
|
||||
* @date 2025-09-16
|
||||
*/
|
||||
|
||||
case OP_LEN: {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
* // Stack after: []
|
||||
*
|
||||
* @author Johannes Findeisen
|
||||
* @date 2025-10-16
|
||||
* @date 2025-09-16
|
||||
*/
|
||||
|
||||
case OP_PRINT: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue