Data update
This commit is contained in:
parent
72eb4943cb
commit
4d5544505c
2347 changed files with 62432 additions and 16731 deletions
164
Task/SHA-1/JavaScript/sha-1.js
Normal file
164
Task/SHA-1/JavaScript/sha-1.js
Normal 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
126
Task/SHA-1/Zig/sha-1.zig
Normal 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});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue