Last active
January 2, 2018 14:16
-
-
Save ekaitz-zarraga/02d58874b0d9757187594319b1ed84bd to your computer and use it in GitHub Desktop.
Pseudocode for CryptoNight made in CoffeeScript
This file contains hidden or 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
# Pseudocode for Cryptonight | |
# -------------------------- | |
# | |
# Written in CoffeeScript for simplicity but untested. | |
# See: | |
# https://cryptonote.org/cns/cns008.txt | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
get_keccak_state = (input)-> | |
keccak_block_width = 1600 # b | |
keccak_capacity = 512 # c | |
# final_state expects a list of bytes for simplicity | |
final_state = keccak input, keccak_block_width, keccak_capacity | |
return final_state | |
scratchpad_init = (final_state)-> | |
scratchpad = [] | |
# +-------------------------------------------------------------+ | |
# | Final state | | |
# +-------------+--------------+---------------+----------------+ | |
# | Bytes 0..31 | Bytes 32..63 | Bytes 64..191 | Bytes 192..199 | | |
# +-------------+--------------+---------------+----------------+ | |
# Make the keys with the first part of the final state | |
# Expand to 10 round keys | |
keys = aes256_expand_key final_state[0..31], 10 | |
# Make 8 blocks of 16 bytes with the third part of the final state | |
initial_blocks = final_state[64..191] | |
blocks = [] | |
for i in [0..7] | |
blocks[i] = initial_blocks[i*16..(i+1)*(16)] | |
# Fill the scratchpad | |
s_byte = 0 | |
while s_byte < 2097152 | |
# Encrypt each block where aes256_round function does: SubBytes, | |
# ShiftRows and MixColumns on the block and the result is XORed with | |
# the key. Note: the first and the last are not special like in | |
# standard AES. | |
for i in [0..9] | |
blocks = (aes256_round b, keys[i] for b in blocks) | |
for block in blocks | |
for byte in block | |
scratchpad[s_byte] = byte | |
s_byte++ | |
return scratchpad | |
memory_hard_loop = (final_state, scratchpad) -> | |
# define a and b variables | |
vars = xor final_state[0..31], final_state[32..63] | |
a = vars[0..15] | |
b = vars[16..31] | |
# Memory-hard loop | |
iter = 0 | |
while iter < 524288 | |
addr = to_scratchpad_address a | |
scratchpad[addr] = aes256_round scratchspad[addr], a | |
[b, scratchpad[addr]] = [scratchpadd[addr], xor b, scratchpad[addr]] | |
addr = to_scratchpad_address b | |
a = _8byte_add( a, _8byte_mul(b, scratchpad[addr])) | |
[a, scratchpad[addr]] = [xor(a, scratchpad[addr]), a] | |
iter++ | |
# Result calculation | |
keys = aes256_expand_key final_state[32..63], 10 | |
block = final_state[64..191] | |
iters = 0 | |
while iters < scratchpad.length()/128 | |
# Encrypt like before | |
block = xor block, scratchpad[i..i*128-1] | |
for i in [0..9] | |
block = aes256_round block, keys[i] | |
iters++ | |
# the bytes 64..191 of the Keccak state are replaced with the result | |
final_state[64..191] = block | |
keccak_block_width = 1600 # b | |
keccak_capacity = 512 # c | |
modified_state = keccak_f final_modified_state, keccak_block_width, keccak_capacity | |
# two last bits of the first byte of the modified_state | |
selector = modified_state[0] % 4 | |
functions = | |
0: blake_256 | |
1: groestil_256 | |
2: jh_256 | |
3: skein_256 | |
# result: | |
return functions[selector] modified_state | |
cryptonight = (input)-> | |
final_state = get_keccak_state input | |
scratchpad = scratchpad_init final_state | |
result = memory_hard_loop final_state, scratchpad | |
return result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment