-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from crema-labs/feat/key-expansion
feat: add key expansion and sbox logic
- Loading branch information
Showing
9 changed files
with
641 additions
and
32 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
pragma circom 2.0.0; | ||
|
||
include "sbox128.circom"; | ||
include "../node_modules/circomlib/circuits/comparators.circom"; | ||
include "../node_modules/circomlib/circuits/bitify.circom"; | ||
include "../node_modules/circomlib/circuits/gates.circom"; | ||
|
||
//nk is the number of keys which can be 4, 6, 8 | ||
//nr is the number of rounds which can be 10, 12, 14 | ||
template KeyExpansion(nk, nr) { | ||
signal input key[nk * 4]; | ||
|
||
var totalWords = (4 * (nr + 1)); | ||
var effectiveRounds = (totalWords % nk == 0 ? totalWords - nk : totalWords) \ nk; | ||
var leftoverWords = totalWords - (effectiveRounds * nk); | ||
|
||
signal output keyExpanded[totalWords][4]; | ||
|
||
for (var i = 0; i < nk; i++) { | ||
for (var j = 0; j < 4; j++) { | ||
keyExpanded[i][j] <== key[(4 * i) + j]; | ||
} | ||
} | ||
|
||
component nextRound[effectiveRounds]; | ||
|
||
for (var round = 1; round <= effectiveRounds; round++) { | ||
var outputWordLen = round == effectiveRounds ? leftoverWords : nk; | ||
nextRound[round - 1] = NextRound(nk, outputWordLen); | ||
|
||
for (var i = 0; i < nk; i++) { | ||
for (var j = 0; j < 4; j++) { | ||
nextRound[round - 1].key[i][j] <== keyExpanded[(round * nk) + i - nk][j]; | ||
} | ||
} | ||
|
||
nextRound[round - 1].round <== round; | ||
|
||
for (var i = 0; i < outputWordLen; i++) { | ||
for (var j = 0; j < 4; j++) { | ||
keyExpanded[(round * nk) + i][j] <== nextRound[round - 1].nextKey[i][j]; | ||
} | ||
} | ||
} | ||
} | ||
|
||
//nk, output | ||
template NextRound(nk, o){ | ||
signal input key[nk][4]; | ||
signal input round; | ||
signal output nextKey[o][4]; | ||
|
||
component rotateWord = RotateWord(1); | ||
for (var i = 0; i < 4; i++) { | ||
rotateWord.bytes[i] <== key[nk - 1][i]; | ||
} | ||
|
||
component substituteWord[2]; | ||
substituteWord[0] = SubstituteWord(); | ||
substituteWord[0].bytes <== rotateWord.rotated; | ||
|
||
component rcon = RCon(); | ||
rcon.round <== round; | ||
|
||
component xorWord[o + 1]; | ||
xorWord[0] = XorWord(); | ||
xorWord[0].bytes1 <== substituteWord[0].substituted; | ||
xorWord[0].bytes2 <== rcon.out; | ||
|
||
for (var i = 0; i < o; i++) { | ||
xorWord[i+1] = XorWord(); | ||
if (i == 0) { | ||
xorWord[i+1].bytes1 <== xorWord[0].out; | ||
} else if(nk == 8 && i == 4) { | ||
substituteWord[1] = SubstituteWord(); | ||
substituteWord[1].bytes <== nextKey[i - 1]; | ||
xorWord[i+1].bytes1 <== substituteWord[1].substituted; | ||
} else { | ||
xorWord[i+1].bytes1 <== nextKey[i-1]; | ||
} | ||
xorWord[i+1].bytes2 <== key[i]; | ||
|
||
for (var j = 0; j < 4; j++) { | ||
nextKey[i][j] <== xorWord[i+1].out[j]; | ||
} | ||
} | ||
} | ||
|
||
|
||
template BytesToWords(n) { | ||
assert(n % 4 == 0); | ||
signal input bytes[n]; | ||
signal output words[n / 4][n]; | ||
|
||
for (var i = 0; i < n / 4; i++) { | ||
for(var j = 0; j < 4; j++) { | ||
words[i][j] <== bytes[i * 4 + j]; | ||
} | ||
} | ||
} | ||
|
||
template RotateWord(rotation) { | ||
assert(rotation < 4); | ||
signal input bytes[4]; | ||
signal output rotated[4]; | ||
|
||
signal copy[rotation]; | ||
|
||
for(var i = 0; i < rotation; i++) { | ||
copy[i] <== bytes[i]; | ||
} | ||
|
||
for(var i = 0; i < 4 - rotation; i++) { | ||
rotated[i] <== bytes[i + rotation]; | ||
} | ||
|
||
for(var i = 4 - rotation; i < 4; i++) { | ||
rotated[i] <== copy[i - 4 + rotation]; | ||
} | ||
} | ||
|
||
template SubstituteWord() { | ||
signal input bytes[4]; | ||
signal output substituted[4]; | ||
|
||
component sbox[4]; | ||
|
||
for(var i = 0; i < 4; i++) { | ||
sbox[i] = Sbox128(); | ||
sbox[i].in <== bytes[i]; | ||
substituted[i] <== sbox[i].out; | ||
} | ||
} | ||
|
||
template RCon() { | ||
signal input round; | ||
signal output out[4]; | ||
|
||
var rcon[10][4] = [ | ||
[0x01, 0x00, 0x00, 0x00], | ||
[0x02, 0x00, 0x00, 0x00], | ||
[0x04, 0x00, 0x00, 0x00], | ||
[0x08, 0x00, 0x00, 0x00], | ||
[0x10, 0x00, 0x00, 0x00], | ||
[0x20, 0x00, 0x00, 0x00], | ||
[0x40, 0x00, 0x00, 0x00], | ||
[0x80, 0x00, 0x00, 0x00], | ||
[0x1b, 0x00, 0x00, 0x00], | ||
[0x36, 0x00, 0x00, 0x00] | ||
]; | ||
|
||
component isEqual[10]; | ||
signal sum[10][4]; | ||
|
||
for (var i = 0; i < 10; i++) { | ||
isEqual[i] = IsEqual(); | ||
isEqual[i].in[0] <== round - 1; | ||
isEqual[i].in[1] <== i; | ||
} | ||
|
||
sum[0] <== [isEqual[0].out * rcon[0][0], isEqual[1].out * rcon[0][1], isEqual[2].out * rcon[0][2], isEqual[3].out * rcon[0][3]]; | ||
for (var i = 1; i < 10; i++) { | ||
for (var j = 0; j < 4; j++) { | ||
sum[i][j] <== sum[i - 1][j] + isEqual[i].out * rcon[i][j]; | ||
} | ||
} | ||
|
||
out <== sum[9]; | ||
} | ||
|
||
template XorWord() { | ||
signal input bytes1[4]; | ||
signal input bytes2[4]; | ||
|
||
component n2b[4 * 2]; | ||
component b2n[4]; | ||
component xor[4][8]; | ||
|
||
signal output out[4]; | ||
|
||
for(var i = 0; i < 4; i++) { | ||
n2b[2 * i] = Num2Bits(8); | ||
n2b[2 * i + 1] = Num2Bits(8); | ||
n2b[2 * i].in <== bytes1[i]; | ||
n2b[2 * i + 1].in <== bytes2[i]; | ||
b2n[i] = Bits2Num(8); | ||
|
||
for (var j = 0; j < 8; j++) { | ||
xor[i][j] = XOR(); | ||
xor[i][j].a <== n2b[2 * i].out[j]; | ||
xor[i][j].b <== n2b[2 * i + 1].out[j]; | ||
b2n[i].in[j] <== xor[i][j].out; | ||
} | ||
|
||
out[i] <== b2n[i].out; | ||
} | ||
} | ||
|
||
template WordSelector() { | ||
signal input condition; | ||
signal input bytes1[4]; | ||
signal input bytes2[4]; | ||
signal output out[4]; | ||
|
||
for (var i = 0; i < 4; i++) { | ||
out[i] <== condition * (bytes1[i] - bytes2[i]) + bytes2[i]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
pragma circom 2.0.0; | ||
|
||
include "circomlib/circuits/comparators.circom"; | ||
|
||
template Sbox128() { | ||
signal input in; | ||
signal output out; | ||
|
||
var sbox[16 * 16] = [ | ||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, | ||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, | ||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, | ||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, | ||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, | ||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, | ||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, | ||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, | ||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, | ||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, | ||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, | ||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, | ||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, | ||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, | ||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, | ||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 | ||
]; | ||
|
||
out <-- sbox[in]; | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.