September Morn Update

This commit is contained in:
Ingy döt Net 2019-09-12 10:33:56 -07:00
parent 4e2d22a71d
commit aac6731f2c
6856 changed files with 141342 additions and 21127 deletions

View file

@ -1,3 +1,31 @@
/// Represent digest with ABCD
sealed public class Digest
{
public uint A;
public uint B;
public uint C;
public uint D;
public Digest()
{
A=(uint)MD5InitializerConstant.A;
B=(uint)MD5InitializerConstant.B;
C=(uint)MD5InitializerConstant.C;
D=(uint)MD5InitializerConstant.D;
}
public override string ToString()
{
string st ;
st= MD5Helper.ReverseByte(A).ToString("X8")+
MD5Helper.ReverseByte(B).ToString("X8")+
MD5Helper.ReverseByte(C).ToString("X8")+
MD5Helper.ReverseByte(D).ToString("X8");
return st;
}
}
public class MD5
{
/***********************VARIABLES************************************/

View file

@ -0,0 +1,125 @@
class MD5 {
private static final int INIT_A = 0x67452301
private static final int INIT_B = (int)0xEFCDAB89L
private static final int INIT_C = (int)0x98BADCFEL
private static final int INIT_D = 0x10325476
private static final int[] SHIFT_AMTS = [
7, 12, 17, 22,
5, 9, 14, 20,
4, 11, 16, 23,
6, 10, 15, 21
]
private static final int[] TABLE_T = new int[64]
static
{
for (int i in 0..63)
TABLE_T[i] = (int)(long)((1L << 32) * Math.abs(Math.sin(i + 1)))
}
static byte[] computeMD5(byte[] message)
{
int messageLenBytes = message.length
int numBlocks = ((messageLenBytes + 8) >>> 6) + 1
int totalLen = numBlocks << 6
byte[] paddingBytes = new byte[totalLen - messageLenBytes]
paddingBytes[0] = (byte)0x80
long messageLenBits = (long)messageLenBytes << 3
for (int i in 0..7)
{
paddingBytes[paddingBytes.length - 8 + i] = (byte)messageLenBits
messageLenBits >>>= 8
}
int a = INIT_A
int b = INIT_B
int c = INIT_C
int d = INIT_D
int[] buffer = new int[16]
for (int i in 0..(numBlocks - 1))
{
int index = i << 6
for (int j in 0..63) {
buffer[j >>> 2] = ((int) ((index < messageLenBytes) ? message[index] : paddingBytes[index - messageLenBytes]) << 24) | (buffer[j >>> 2] >>> 8)
index++
}
int originalA = a
int originalB = b
int originalC = c
int originalD = d
for (int j in 0..63)
{
int div16 = j >>> 4
int f = 0
int bufferIndex = j
switch (div16)
{
case 0:
f = (b & c) | (~b & d)
break
case 1:
f = (b & d) | (c & ~d)
bufferIndex = (bufferIndex * 5 + 1) & 0x0F
break
case 2:
f = b ^ c ^ d
bufferIndex = (bufferIndex * 3 + 5) & 0x0F
break
case 3:
f = c ^ (b | ~d)
bufferIndex = (bufferIndex * 7) & 0x0F
break
}
int temp = b + Integer.rotateLeft(a + f + buffer[bufferIndex] + TABLE_T[j], SHIFT_AMTS[(div16 << 2) | (j & 3)])
a = d
d = c
c = b
b = temp
}
a += originalA
b += originalB
c += originalC
d += originalD
}
byte[] md5 = new byte[16]
int count = 0
for (int i in 0..3)
{
int n = (i == 0) ? a : ((i == 1) ? b : ((i == 2) ? c : d))
for (int j in 0..3)
{
md5[count++] = (byte)n
n >>>= 8
}
}
return md5
}
static String toHexString(byte[] b)
{
StringBuilder sb = new StringBuilder()
for (int i in 0..(b.length - 1))
{
sb.append(String.format("%02X", b[i] & 0xFF))
}
return sb.toString()
}
static void main(String[] args)
{
String[] testStrings = ["", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
"12345678901234567890123456789012345678901234567890123456789012345678901234567890" ]
for (String s : testStrings)
System.out.println("0x" + toHexString(computeMD5(s.getBytes())) + " <== \"" + s + "\"")
}
}

View file

@ -0,0 +1,76 @@
# a rather literal translation of the pseudocode at https://en.wikipedia.org/wiki/MD5
const s = UInt32[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]
const K = UInt32[0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf,
0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1,
0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562,
0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681,
0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905,
0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122,
0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6,
0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8,
0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3,
0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314,
0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391]
function md5(msgbytes)
a0::UInt32 = 0x67452301 # A
b0::UInt32 = 0xefcdab89 # B
c0::UInt32 = 0x98badcfe # C
d0::UInt32 = 0x10325476 # D
oldlen = length(msgbytes)
umsg = push!([UInt8(b) for b in msgbytes], UInt8(0x80))
while length(umsg) % 64 != 56
push!(umsg, UInt8(0))
end
append!(umsg, reinterpret(UInt8, [htol(UInt64(oldlen) * 8)]))
for j in 1:64:length(umsg)-1
arr = view(umsg, j:j+63)
M = [reinterpret(UInt32, arr[k:k+3])[1] for k in 1:4:62]
A = a0
B = b0
C = c0
D = d0
for i in 0:63
if 0 ≤ i ≤ 15
F = D ⊻ (B & (C ⊻ D))
g = i
elseif 16 ≤ i ≤ 31
F = C ⊻ (D & (B ⊻ C))
g = (5 * i + 1) % 16
elseif 32 ≤ i ≤ 47
F = B ⊻ C ⊻ D
g = (3 * i + 5) % 16
elseif 48 ≤ i ≤ 63
F = C ⊻ (B | (~D))
g = (7 * i) % 16
end
F += A + K[i+1] + M[g+1]
A = D
D = C
C = B
B += ((F) << s[i+1]) | (F >> (32 - s[i+1]))
end
a0 += A
b0 += B
c0 += C
d0 += D
end
digest = join(map(x -> lpad(string(x, base=16), 2, '0'), reinterpret(UInt8, [a0, b0, c0, d0])), "") # Output is in little-endian
end
for pair in [0xd41d8cd98f00b204e9800998ecf8427e => "", 0x0cc175b9c0f1b6a831c399e269772661 => "a",
0x900150983cd24fb0d6963f7d28e17f72 => "abc", 0xf96b697d7cb7938d525a2f31aaf161d0 => "message digest",
0xc3fcd3d76192e4007dfb496cca67e13b => "abcdefghijklmnopqrstuvwxyz",
0xd174ab98d277d9f5a5611c2c9f419d9f => "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
0x57edf4a22be3c955ac49da2e2107b67a => "12345678901234567890123456789012345678901234567890123456789012345678901234567890"]
println("MD5 of $(pair[2]) is $(md5(pair[2])), which checks with $(string(pair[1], base=16)).")
end

View file

@ -0,0 +1,238 @@
#![allow(non_snake_case)] // RFC 1321 uses many capitalized variables
use std::mem;
fn md5(mut msg: Vec<u8>) -> (u32, u32, u32, u32) {
let bitcount = msg.len().saturating_mul(8) as u64;
// Step 1: Append Padding Bits
msg.push(0b10000000);
while (msg.len() * 8) % 512 != 448 {
msg.push(0u8);
}
// Step 2. Append Length (64 bit integer)
msg.extend(&[
bitcount as u8,
(bitcount >> 8) as u8,
(bitcount >> 16) as u8,
(bitcount >> 24) as u8,
(bitcount >> 32) as u8,
(bitcount >> 40) as u8,
(bitcount >> 48) as u8,
(bitcount >> 56) as u8,
]);
// Step 3. Initialize MD Buffer
/*A four-word buffer (A,B,C,D) is used to compute the message digest.
Here each of A, B, C, D is a 32-bit register.*/
let mut A = 0x67452301u32;
let mut B = 0xefcdab89u32;
let mut C = 0x98badcfeu32;
let mut D = 0x10325476u32;
// Step 4. Process Message in 16-Word Blocks
/* We first define four auxiliary functions */
let F = |X: u32, Y: u32, Z: u32| -> u32 { X & Y | !X & Z };
let G = |X: u32, Y: u32, Z: u32| -> u32 { X & Z | Y & !Z };
let H = |X: u32, Y: u32, Z: u32| -> u32 { X ^ Y ^ Z };
let I = |X: u32, Y: u32, Z: u32| -> u32 { Y ^ (X | !Z) };
/* This step uses a 64-element table T[1 ... 64] constructed from the sine function. */
let T = [
0x00000000, // enable use as a 1-indexed table
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613,
0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193,
0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d,
0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122,
0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,
0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244,
0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb,
0xeb86d391,
];
/* Process each 16-word block. (since 1 word is 4 bytes, then 16 words is 64 bytes) */
for mut block in msg.chunks_exact_mut(64) {
/* Copy block into X. */
#![allow(unused_mut)]
let mut X = unsafe { mem::transmute::<&mut [u8], &mut [u32]>(&mut block) };
#[cfg(target_endian = "big")]
for j in 0..16 {
X[j] = X[j].swap_bytes();
}
/* Save Registers A,B,C,D */
let AA = A;
let BB = B;
let CC = C;
let DD = D;
/* Round 1. Let [abcd k s i] denote the operation
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
macro_rules! op1 {
($a:ident,$b:ident,$c:ident,$d:ident,$k:expr,$s:expr,$i:expr) => {
$a = $b.wrapping_add(
($a.wrapping_add(F($b, $c, $d))
.wrapping_add(X[$k])
.wrapping_add(T[$i]))
.rotate_left($s),
)
};
}
/* Do the following 16 operations. */
op1!(A, B, C, D, 0, 7, 1);
op1!(D, A, B, C, 1, 12, 2);
op1!(C, D, A, B, 2, 17, 3);
op1!(B, C, D, A, 3, 22, 4);
op1!(A, B, C, D, 4, 7, 5);
op1!(D, A, B, C, 5, 12, 6);
op1!(C, D, A, B, 6, 17, 7);
op1!(B, C, D, A, 7, 22, 8);
op1!(A, B, C, D, 8, 7, 9);
op1!(D, A, B, C, 9, 12, 10);
op1!(C, D, A, B, 10, 17, 11);
op1!(B, C, D, A, 11, 22, 12);
op1!(A, B, C, D, 12, 7, 13);
op1!(D, A, B, C, 13, 12, 14);
op1!(C, D, A, B, 14, 17, 15);
op1!(B, C, D, A, 15, 22, 16);
/* Round 2. Let [abcd k s i] denote the operation
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
macro_rules! op2 {
($a:ident,$b:ident,$c:ident,$d:ident,$k:expr,$s:expr,$i:expr) => {
$a = $b.wrapping_add(
($a.wrapping_add(G($b, $c, $d))
.wrapping_add(X[$k])
.wrapping_add(T[$i]))
.rotate_left($s),
)
};
}
/* Do the following 16 operations. */
op2!(A, B, C, D, 1, 5, 17);
op2!(D, A, B, C, 6, 9, 18);
op2!(C, D, A, B, 11, 14, 19);
op2!(B, C, D, A, 0, 20, 20);
op2!(A, B, C, D, 5, 5, 21);
op2!(D, A, B, C, 10, 9, 22);
op2!(C, D, A, B, 15, 14, 23);
op2!(B, C, D, A, 4, 20, 24);
op2!(A, B, C, D, 9, 5, 25);
op2!(D, A, B, C, 14, 9, 26);
op2!(C, D, A, B, 3, 14, 27);
op2!(B, C, D, A, 8, 20, 28);
op2!(A, B, C, D, 13, 5, 29);
op2!(D, A, B, C, 2, 9, 30);
op2!(C, D, A, B, 7, 14, 31);
op2!(B, C, D, A, 12, 20, 32);
/* Round 3. Let [abcd k s t] denote the operation
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
macro_rules! op3 {
($a:ident,$b:ident,$c:ident,$d:ident,$k:expr,$s:expr,$i:expr) => {
$a = $b.wrapping_add(
($a.wrapping_add(H($b, $c, $d))
.wrapping_add(X[$k])
.wrapping_add(T[$i]))
.rotate_left($s),
)
};
}
/* Do the following 16 operations. */
op3!(A, B, C, D, 5, 4, 33);
op3!(D, A, B, C, 8, 11, 34);
op3!(C, D, A, B, 11, 16, 35);
op3!(B, C, D, A, 14, 23, 36);
op3!(A, B, C, D, 1, 4, 37);
op3!(D, A, B, C, 4, 11, 38);
op3!(C, D, A, B, 7, 16, 39);
op3!(B, C, D, A, 10, 23, 40);
op3!(A, B, C, D, 13, 4, 41);
op3!(D, A, B, C, 0, 11, 42);
op3!(C, D, A, B, 3, 16, 43);
op3!(B, C, D, A, 6, 23, 44);
op3!(A, B, C, D, 9, 4, 45);
op3!(D, A, B, C, 12, 11, 46);
op3!(C, D, A, B, 15, 16, 47);
op3!(B, C, D, A, 2, 23, 48);
/* Round 4. Let [abcd k s t] denote the operation
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
macro_rules! op4 {
($a:ident,$b:ident,$c:ident,$d:ident,$k:expr,$s:expr,$i:expr) => {
$a = $b.wrapping_add(
($a.wrapping_add(I($b, $c, $d))
.wrapping_add(X[$k])
.wrapping_add(T[$i]))
.rotate_left($s),
)
};
}
/* Do the following 16 operations. */
op4!(A, B, C, D, 0, 6, 49);
op4!(D, A, B, C, 7, 10, 50);
op4!(C, D, A, B, 14, 15, 51);
op4!(B, C, D, A, 5, 21, 52);
op4!(A, B, C, D, 12, 6, 53);
op4!(D, A, B, C, 3, 10, 54);
op4!(C, D, A, B, 10, 15, 55);
op4!(B, C, D, A, 1, 21, 56);
op4!(A, B, C, D, 8, 6, 57);
op4!(D, A, B, C, 15, 10, 58);
op4!(C, D, A, B, 6, 15, 59);
op4!(B, C, D, A, 13, 21, 60);
op4!(A, B, C, D, 4, 6, 61);
op4!(D, A, B, C, 11, 10, 62);
op4!(C, D, A, B, 2, 15, 63);
op4!(B, C, D, A, 9, 21, 64);
/* . . . increment each of the four registers by the value
it had before this block was started.) */
A = A.wrapping_add(AA);
B = B.wrapping_add(BB);
C = C.wrapping_add(CC);
D = D.wrapping_add(DD);
}
(
A.swap_bytes(),
B.swap_bytes(),
C.swap_bytes(),
D.swap_bytes(),
)
}
fn md5_utf8(smsg: &str) -> String {
let mut msg = vec![0u8; 0];
msg.extend(smsg.as_bytes());
let (A, B, C, D) = md5(msg);
format!("{:08x}{:08x}{:08x}{:08x}", A, B, C, D)
}
fn main() {
assert!(md5_utf8("") == "d41d8cd98f00b204e9800998ecf8427e");
assert!(md5_utf8("a") == "0cc175b9c0f1b6a831c399e269772661");
assert!(md5_utf8("abc") == "900150983cd24fb0d6963f7d28e17f72");
assert!(md5_utf8("message digest") == "f96b697d7cb7938d525a2f31aaf161d0");
assert!(md5_utf8("abcdefghijklmnopqrstuvwxyz") == "c3fcd3d76192e4007dfb496cca67e13b");
assert!(md5_utf8("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") == "d174ab98d277d9f5a5611c2c9f419d9f");
assert!(md5_utf8("12345678901234567890123456789012345678901234567890123456789012345678901234567890") == "57edf4a22be3c955ac49da2e2107b67a");
}

View file

@ -28,7 +28,7 @@ class MD5(String msg) {
].flat
func radix(Number b, Array a) {
^a -> map {|i| b**i * a[i] }.sum(0)
^a -> sum {|i| b**i * a[i] }
}
func little_endian(Number w, Number n, Array v) {