Data update

This commit is contained in:
Ingy döt Net 2025-06-11 20:16:52 -04:00
parent 72eb4943cb
commit 4d5544505c
2347 changed files with 62432 additions and 16731 deletions

View file

@ -0,0 +1,164 @@
class SHA1 {
constructor() {
// Constants
this.BLOCK_LENGTH = 64; // Bytes
this.H = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
this.K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];
}
/**
* Rotates left (circular left shift) on a 32-bit number.
* @param {number} n - The 32-bit number.
* @param {number} bits - The number of bits to rotate.
* @returns {number} The rotated 32-bit number.
*/
_rotl(n, bits) {
// Ensure n is treated as 32-bit for the shift operations
return ((n << bits) | (n >>> (32 - bits))) | 0; // | 0 ensures result is 32-bit signed int
}
/**
* Adds SHA-1 padding to the message bytes.
* @param {Uint8Array} messageBytes - The message as bytes.
* @returns {Uint8Array} The padded message bytes.
*/
_addPadding(messageBytes) {
const msgLenBytes = messageBytes.length;
// Use BigInt for potentially large bit lengths
const bitLength = BigInt(msgLenBytes) * 8n;
// Calculate the total padded length in bytes
// Need msgLenBytes + 1 (for 0x80) + k (zeros) + 8 (length) = N * 64
// msgLenBytes + 9 + k = N * 64
// The number of zero bytes 'k' needed is:
// k = (64 - (msgLenBytes + 9) % 64) % 64
const k = (this.BLOCK_LENGTH - ((msgLenBytes + 9) % this.BLOCK_LENGTH)) % this.BLOCK_LENGTH;
const paddedLength = msgLenBytes + 1 + k + 8;
const paddedBytes = new Uint8Array(paddedLength);
// 1. Copy original message
paddedBytes.set(messageBytes);
// 2. Append a single '1' bit (0x80 byte)
paddedBytes[msgLenBytes] = 0x80;
// 3. Append K '0' bits (zero bytes). Uint8Array initializes to 0, so this is implicit.
// 4. Append length L as a 64-bit big-endian integer.
const lengthOffset = paddedLength - 8;
for (let i = 0; i < 8; i++) {
// Extract byte from BigInt bitLength
const shift = BigInt(i) * 8n;
// Place it in big-endian order (most significant byte first)
paddedBytes[lengthOffset + 7 - i] = Number((bitLength >> shift) & 0xffn);
}
return paddedBytes;
}
/**
* Computes the SHA-1 hash of a message string.
* @param {string} message - The input message string.
* @returns {string} The SHA-1 hash as a 40-character hex string.
*/
messageDigest(message) {
// 1. Convert message string to UTF-8 bytes
const encoder = new TextEncoder(); // Assumes UTF-8
const messageBytes = encoder.encode(message);
// 2. Add padding
const paddedBytes = this._addPadding(messageBytes);
// 3. Initialize hash values
let state = [...this.H]; // Create a working copy
// 4. Process message in 64-byte (512-bit) blocks
for (let i = 0; i < paddedBytes.length; i += this.BLOCK_LENGTH) {
const blockBytes = paddedBytes.subarray(i, i + this.BLOCK_LENGTH);
// Prepare the message schedule (80 32-bit words)
const W = new Array(80);
// a. Copy block into first 16 words (big-endian)
for (let t = 0; t < 16; t++) {
const offset = t * 4;
W[t] = ((blockBytes[offset] << 24) |
(blockBytes[offset + 1] << 16) |
(blockBytes[offset + 2] << 8) |
(blockBytes[offset + 3])) | 0; // | 0 ensures 32-bit signed int
}
// b. Extend the first 16 words into the remaining 64 words
for (let t = 16; t < 80; t++) {
const wt = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
W[t] = this._rotl(wt, 1);
}
// Initialize hash value for this block
let a = state[0];
let b = state[1];
let c = state[2];
let d = state[3];
let e = state[4];
// Main loop
for (let t = 0; t < 80; t++) {
let f, k;
const round = Math.floor(t / 20);
switch (round) {
case 0: // Rounds 0-19
f = (b & c) | (~b & d);
k = this.K[0];
break;
case 1: // Rounds 20-39
f = b ^ c ^ d;
k = this.K[1];
break;
case 2: // Rounds 40-59
f = (b & c) | (b & d) | (c & d);
k = this.K[2];
break;
case 3: // Rounds 60-79
f = b ^ c ^ d;
k = this.K[3];
break;
}
// Ensure all additions are performed modulo 2^32
const temp = (this._rotl(a, 5) + f + e + k + W[t]) | 0;
e = d;
d = c;
c = this._rotl(b, 30);
b = a;
a = temp;
}
// Add this block's hash to the result so far (modulo 2^32)
state[0] = (state[0] + a) | 0;
state[1] = (state[1] + b) | 0;
state[2] = (state[2] + c) | 0;
state[3] = (state[3] + d) | 0;
state[4] = (state[4] + e) | 0;
}
// 5. Produce the final hash value (big-endian) as a hex string
let hexHash = "";
for (const h of state) {
// Convert each 32-bit component to hex, padding with '0'
// Use >>> 0 to treat h as unsigned before converting to hex parts
const unsignedH = h >>> 0;
hexHash += (unsignedH >>> 24).toString(16).padStart(2, '0');
hexHash += ((unsignedH >>> 16) & 0xff).toString(16).padStart(2, '0');
hexHash += ((unsignedH >>> 8) & 0xff).toString(16).padStart(2, '0');
hexHash += (unsignedH & 0xff).toString(16).padStart(2, '0');
}
return hexHash;
}
}
// --- Main execution (equivalent to C++ main) ---
const sha1 = new SHA1();
const message = "Rosetta Code";
const digest = sha1.messageDigest(message);
console.log(digest);

126
Task/SHA-1/Zig/sha-1.zig Normal file
View file

@ -0,0 +1,126 @@
const std = @import("std");
const SHA1 = struct {
const BLOCK_LENGTH: u32 = 64;
fn messageDigest(message: []const u8) ![40]u8 {
var state = [5]u32{ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
const bytes = try addPadding(message);
var i: usize = 0;
while (i < bytes.len / BLOCK_LENGTH) : (i += 1) {
var values = [_]u32{0} ** 80;
var j: u32 = 0;
while (j < BLOCK_LENGTH) : (j += 1) {
values[j / 4] |= @as(u32, @intCast(bytes[i * BLOCK_LENGTH + j] & 0xff)) << @intCast((3 - j % 4) * 8);
}
j = 16;
while (j < 80) : (j += 1) {
const value = values[j - 3] ^ values[j - 8] ^ values[j - 14] ^ values[j - 16];
values[j] = std.math.rotl(u32, value, 1);
}
var a = state[0];
var b = state[1];
var c = state[2];
var d = state[3];
var e = state[4];
var f: u32 = 0;
var k: u32 = 0;
j = 0;
while (j < 80) : (j += 1) {
switch (j / 20) {
0 => {
f = (b & c) | (~b & d);
k = 0x5a827999;
},
1 => {
f = b ^ c ^ d;
k = 0x6ed9eba1;
},
2 => {
f = (b & c) | (b & d) | (c & d);
k = 0x8f1bbcdc;
},
3 => {
f = b ^ c ^ d;
k = 0xca62c1d6;
},
else => unreachable,
}
// Use wrapping add to prevent integer overflow panics
const rotated_a = std.math.rotl(u32, a, 5);
const temp = @addWithOverflow(rotated_a, f)[0];
const temp2 = @addWithOverflow(temp, e)[0];
const temp3 = @addWithOverflow(temp2, k)[0];
const temp4 = @addWithOverflow(temp3, values[j])[0];
e = d;
d = c;
c = std.math.rotl(u32, b, 30);
b = a;
a = temp4;
}
// Use wrapping adds for state updates
state[0] = @addWithOverflow(state[0], a)[0];
state[1] = @addWithOverflow(state[1], b)[0];
state[2] = @addWithOverflow(state[2], c)[0];
state[3] = @addWithOverflow(state[3], d)[0];
state[4] = @addWithOverflow(state[4], e)[0];
}
var result: [40]u8 = undefined;
var buffer: [8]u8 = undefined;
for (0..20) |my_i| {
const byte_value: u8 = @intCast((state[my_i / 4] >> @intCast(24 - (my_i % 4) * 8)) & 0xff);
_ = try std.fmt.bufPrint(buffer[0..2], "{x:0>2}", .{byte_value});
result[my_i * 2] = buffer[0];
result[my_i * 2 + 1] = buffer[1];
}
return result;
}
fn addPadding(message: []const u8) ![]u8 {
const allocator = std.heap.page_allocator;
// Initialize with the message
var bytes = std.ArrayList(u8).init(allocator);
defer bytes.deinit();
try bytes.appendSlice(message);
try bytes.append(0x80);
var padding: u32 = BLOCK_LENGTH - @as(u32, @intCast(bytes.items.len % BLOCK_LENGTH));
if (padding < 8) {
padding += BLOCK_LENGTH;
}
var i: u32 = 0;
while (i < padding - 8) : (i += 1) {
try bytes.append(0x0);
}
const bit_length: u64 = 8 * message.len;
i = 0;
while (i < 8) : (i += 1) {
const shift_amount: u6 = @intCast(8 * (7 - i)); // Explicit cast to u6 for shift
try bytes.append(@intCast((bit_length >> shift_amount) & 0xff));
}
return bytes.toOwnedSlice();
}
};
pub fn main() !void {
const message = "Rosetta Code";
const result = try SHA1.messageDigest(message);
const stdout = std.io.getStdOut().writer();
try stdout.print("{s}\n", .{result});
}