Skip to content

Commit

Permalink
implement block function and test
Browse files Browse the repository at this point in the history
  • Loading branch information
0x471 committed Aug 29, 2024
1 parent f81ca6c commit 27bd3ee
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 72 deletions.
48 changes: 22 additions & 26 deletions src/chacha20.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { jest } from '@jest/globals';
import { UInt32 } from 'o1js';
import { ChaChaState } from './chacha20';
import { chacha20Block, ChaChaState } from './chacha20';

jest.useFakeTimers();

export {toHexString}
function toHexString(value: UInt32): string {
const numberValue = value.toBigint();
return numberValue.toString(16).padStart(8, '0');
Expand Down Expand Up @@ -114,32 +115,27 @@ describe('ChaCha', () => {
expect(receivedHex).toBe(expectedHex);
}

// Assert toLe4Bytes conversion
const le4Bytes = chachaState.toLe4Bytes();

const expectedLe4Bytes: UInt32[] = [
UInt32.fromValue(0x65787061n), // Little-endian of 0x61707865
UInt32.fromValue(0x6E642033n), // Little-endian of 0x3320646e
UInt32.fromValue(0x322D6279n), // Little-endian of 0x79622d32
UInt32.fromValue(0x7465206Bn), // Little-endian of 0x6b206574
UInt32.fromValue(0x00010203n), // Little-endian of 0x03020100
UInt32.fromValue(0x04050607n), // Little-endian of 0x07060504
UInt32.fromValue(0x08090A0Bn), // Little-endian of 0x0b0a0908
UInt32.fromValue(0x0C0D0E0Fn), // Little-endian of 0x0f0e0d0c
UInt32.fromValue(0x10111213n), // Little-endian of 0x13121110
UInt32.fromValue(0x14151617n), // Little-endian of 0x17161514
UInt32.fromValue(0x18191A1Bn), // Little-endian of 0x1b1a1918
UInt32.fromValue(0x1C1D1E1Fn), // Little-endian of 0x1f1e1d1c
UInt32.fromValue(0x01000000n), // Little-endian of 0x00000001
UInt32.fromValue(0x00000009n), // Little-endian of 0x09000000
UInt32.fromValue(0x0000004An), // Little-endian of 0x4a000000
UInt32.fromValue(0x00000000n) // Little-endian of 0x00000000
});
it("should calculate the block function correctly", () => {
let key = "00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f";
let nonce = "00:00:00:09:00:00:00:4a:00:00:00:00";
const counter = 1;

const keyArray = octetsToUint32Array(key);
const nonceArray = octetsToUint32Array(nonce);

const expectedState: UInt32[] = [
UInt32.fromValue(0xe4e7f110n), UInt32.fromValue(0x15593bd1n), UInt32.fromValue(0x1fdd0f50n), UInt32.fromValue(0xc47120a3n),
UInt32.fromValue(0xc7f4d1c7n), UInt32.fromValue(0x0368c033n), UInt32.fromValue(0x9aaa2204n), UInt32.fromValue(0x4e6cd4c3n),
UInt32.fromValue(0x466482d2n), UInt32.fromValue(0x09aa9f07n), UInt32.fromValue(0x05d7c214n), UInt32.fromValue(0xa2028bd9n),
UInt32.fromValue(0xd19c12b5n), UInt32.fromValue(0xb94e16den), UInt32.fromValue(0xe883d0cbn), UInt32.fromValue(0x4e3c50a2n)
];

for (let i = 0; i < le4Bytes.length; i++) {
expect(le4Bytes[i]).toEqual(expectedLe4Bytes[i]);
let chachaState = chacha20Block(keyArray, nonceArray, counter);
for (let i = 0; i < chachaState.length; i++) {
const receivedHex = toHexString(chachaState[i]);
const expectedHex = toHexString(expectedState[i]);
expect(receivedHex).toBe(expectedHex);
}

});
// TODO: add tests for block generation
})
});
61 changes: 15 additions & 46 deletions src/chacha20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,25 @@ import {
Field,
UInt8,
} from 'o1js';
import { toHexString } from './chacha20.test';

export { ChaChaState };
export { ChaChaState, chacha20Block };

function chacha20Block(key: Uint32Array, nonce: Uint32Array, counter: number): UInt32[] {
let state = new ChaChaState(key, nonce, counter);
let workingState = new ChaChaState(key, nonce, counter);

for (let i = 0; i < 10; i++) {
ChaChaState.innerBlock(workingState.state);
}

workingState.add(state);
return workingState.state;
}

class ChaChaState {
state: UInt32[];
constructor(public key: Uint32Array, nonce: Uint32Array, counter: number) {
constructor(key: Uint32Array, nonce: Uint32Array, counter: number) {
const stateValues: number[] = [
0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, // ChaCha constants
key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7],
Expand Down Expand Up @@ -68,48 +81,4 @@ class ChaChaState {
this.state[i] = UInt32.fromFields([Field.from((this.state[i].toBigint() + other.state[i].toBigint()) & 0xFFFFFFFFn)]);
}
}

toLe4Bytes(): UInt32[] {
const res: UInt32[] = [];

for (let i = 0; i < 16; i++) {
const value = this.state[i].toBigint();

// Convert to little-endian 4 bytes
const byte0 = (value & 0xFFn);
const byte1 = (value >> 8n) & 0xFFn;
const byte2 = (value >> 16n) & 0xFFn;
const byte3 = (value >> 24n) & 0xFFn;

const leValue = (byte0 << 24n) | (byte1 << 16n) | (byte2 << 8n) | byte3;
res.push(UInt32.fromValue(leValue));
}

return res;
}



// chacha20Block(): UInt32[] {
// // Convert each value in this.state to UInt32
// const workingState: UInt32[] = this.state.map(value => UInt32.fromValue(value.toBigint()));

// // Perform 10 rounds of the inner block function
// for (let i = 0; i < 10; i++) {
// ChaChaState.innerBlock(workingState);
// }

// // Create a new ChaChaState instance from the working state
// const newState = new ChaChaState(
// new Uint32Array(workingState.slice(0, 8).map(v => Number(v.toBigint()))),
// new Uint32Array(workingState.slice(8, 11).map(v => Number(v.toBigint()))),
// Number(workingState[11].toBigint())
// );

// // Add the new state to the current state
// this.add(newState);
// return this.state;
// }


}

0 comments on commit 27bd3ee

Please sign in to comment.