Merge pull request #136 from MyHush/danger

Sync danger to duke
This commit is contained in:
Denio
2020-09-09 14:49:14 +02:00
committed by GitHub
36 changed files with 4705 additions and 123 deletions

View File

@@ -1,33 +1,56 @@
#!/usr/bin/env perl
# Copyright 2019 The Hush developers
# Copyright 2019-2020 The Hush developers
# Released under the GPLv3
use warnings;
use strict;
# Simulate the total supply on Hush v3 mainnet
# Todo: track FR
# Todo: verify FR off-by-one
my $supply = 0.0;
my $block = 0;
my $satoshis = 100_000_000;
my $amount = int(12.5*$satoshis);
my $block = 0; # Block 0 in Hush Smart chains is the BTC genesis block
my $puposhis = 100_000_000;
my $reward0 = 1_250_000_000;
my $halvings = 0;
my $initial = 6178674 * $puposhis;
my $interval = 1_640_000; # 4 years of 75s blocks
my $stop = shift || -1;
my $totalfr = 0; # total paid out to FR address
my $reward = $reward0;
# Usage: ./hush_supply &> supply.csv
# Usage: ./hush_supply &> supply.csv
# ./hush_supply HEIGHT &> supply.csv # stop at HEIGHT
# Use this to calculate when supply hits a certain value
#while ($supply <= 21_000_000*$satoshis) {
# Use this to calculate when block rewards end
while ($halvings <= 64 && $amount >= 1) {
printf "# block, supply, reward, fr, totalfr, halvings\n";
# We know BR will go to zero between 7 and 8th halvings
while ($halvings <= 10) {
$block++;
if ($block < 5) {
$amount = 40_000 * $satoshis;
my $fr = 0;
# blocks 2-127 of Hush v3 had BR=0
if ($block == 1) {
$reward = $initial; # airdropped funds from Hush v2 mainnet
} elsif ($block > 1 && $block < 128) {
$reward = 0; # blocks 2-127 have BR=0
} else {
# Halving every 840000 blocks
if ($block % 840_000 == 0) {
$amount /= 2;
$halvings++;
$fr = 125_000_000;
if ($block < 340_000) {
$reward = $reward0;
} else {
my $shifted = $block - 340_000;
# Past the first halving
$halvings = 1 + int ($shifted / $interval);
if ($shifted % 840_000 == 0) {
$reward >>= 2;
$fr >>= 2;
}
}
$amount = int(12.5*$satoshis) / (2**$halvings);
}
$supply += $amount;
# block, current supply, block reward amount, number of halvings
printf "%s,%s,%s,%s\n", $block,$supply / $satoshis, $amount / $satoshis, $halvings;
$supply += $reward;
$totalfr += $fr;
# block, current supply, block reward amount, number of halvings, all amounts are in puposhis
printf "%d,%d,%d,%d,%d,%d\n", $block, $supply, $reward, $fr, $totalfr, $halvings;
exit(0) if $block == $stop;
}

33
contrib/hush_supply_old Executable file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env perl
# Copyright 2019-2020 The Hush developers
# Released under the GPLv3
use warnings;
use strict;
my $supply = 0.0;
my $block = 0;
my $satoshis = 100_000_000;
my $amount = int(12.5*$satoshis);
my $halvings = 0;
# Usage: ./hush_supply &> supply.csv
# Use this to calculate when supply hits a certain value
#while ($supply <= 21_000_000*$satoshis) {
# Use this to calculate when block rewards end
while ($halvings <= 64 && $amount >= 1) {
$block++;
if ($block < 5) {
$amount = 40_000 * $satoshis;
} else {
# Halving every 840000 blocks
if ($block % 840_000 == 0) {
$amount /= 2;
$halvings++;
}
$amount = int(12.5*$satoshis) / (2**$halvings);
}
$supply += $amount;
# block, current supply, block reward amount, number of halvings
printf "%s,%s,%s,%s\n", $block,$supply / $satoshis, $amount / $satoshis, $halvings;
}

View File

@@ -0,0 +1,51 @@
#!/usr/bin/env python3
# Copyright (c) 2017 The Bitcoin Core developers
# Copyright (c) 2019-2020 The Hush developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://www.opensource.org/licenses/mit-license.php
"""Test wallet file location."""
import os
from test_framework.util import start_node, stop_node, assert_start_raises_init_error
from test_framework.test_framework import BitcoinTestFramework
class WalletFileTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
def run_test(self):
# test default wallet location
assert os.path.isfile(os.path.join(self.options.tmpdir, "node0", "regtest", "wallet.dat"))
# test alternative wallet file name in datadir
stop_node(self.nodes[0], 0)
self.nodes[0] = start_node(0, self.options.tmpdir, ["-wallet=altwallet.dat"])
assert os.path.isfile(os.path.join(self.options.tmpdir, "node0", "regtest", "altwallet.dat"))
# test wallet file outside datadir
tempname = os.path.join(self.options.tmpdir, "outsidewallet.dat")
stop_node(self.nodes[0], 0)
self.nodes[0] = start_node(0, self.options.tmpdir, ["-wallet=%s" % tempname])
assert os.path.isfile(tempname)
# test the case where absolute path does not exist
assert not os.path.isdir("/this_directory_must_not_exist")
invalidpath = os.path.join("/this_directory_must_not_exist/", "foo.dat")
stop_node(self.nodes[0], 0)
assert_start_raises_init_error(0, "-wallet=%s" % invalidpath,
"Error: Absolute path %s does not exist")
# relative path does not exist
invalidpath = os.path.join("wallet", "foo.dat")
assert_start_raises_init_error(0, "-wallet=%s" % invalidpath,
"Error: Relative path %s does not exist")
# create dir and retry
os.mkdir(os.path.join(self.options.tmpdir, "node0", "regtest", "wallet"))
self.nodes[0] = start_node(0, self.options.tmpdir, ["-wallet=%s" % invalidpath])
if __name__ == '__main__':
WalletFileTest().main()

View File

@@ -0,0 +1,3 @@
# trezor-firmware bip39
Imported from https://github.com/trezor/trezor-firmware/commit/047fcffde1f8530d3aee279b731e5e5f5901590a

281
src/crypto/bip39/bip39.c Normal file
View File

@@ -0,0 +1,281 @@
/**
* Copyright (c) 2013-2014 Tomas Dzetkulic
* Copyright (c) 2013-2014 Pavol Rusnak
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdbool.h>
#include <string.h>
#include "bip39.h"
#include "bip39_english.h"
#include "hmac.h"
#include "memzero.h"
#include "options.h"
#include "pbkdf2.h"
#include "rand.h"
#include "sha2.h"
#if USE_BIP39_CACHE
static int bip39_cache_index = 0;
static CONFIDENTIAL struct {
bool set;
char mnemonic[256];
char passphrase[64];
uint8_t seed[512 / 8];
} bip39_cache[BIP39_CACHE_SIZE];
#endif
const char *mnemonic_generate(int strength) {
if (strength % 32 || strength < 128 || strength > 256) {
return 0;
}
uint8_t data[32] = {0};
random_buffer(data, 32);
const char *r = mnemonic_from_data(data, strength / 8);
memzero(data, sizeof(data));
return r;
}
static CONFIDENTIAL char mnemo[24 * 10];
const char *mnemonic_from_data(const uint8_t *data, int len) {
if (len % 4 || len < 16 || len > 32) {
return 0;
}
uint8_t bits[32 + 1] = {0};
sha256_Raw(data, len, bits);
// checksum
bits[len] = bits[0];
// data
memcpy(bits, data, len);
int mlen = len * 3 / 4;
int i = 0, j = 0, idx = 0;
char *p = mnemo;
for (i = 0; i < mlen; i++) {
idx = 0;
for (j = 0; j < 11; j++) {
idx <<= 1;
idx += (bits[(i * 11 + j) / 8] & (1 << (7 - ((i * 11 + j) % 8)))) > 0;
}
strcpy(p, wordlist[idx]);
p += strlen(wordlist[idx]);
*p = (i < mlen - 1) ? ' ' : 0;
p++;
}
memzero(bits, sizeof(bits));
return mnemo;
}
void mnemonic_clear(void) { memzero(mnemo, sizeof(mnemo)); }
int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy) {
if (!mnemonic) {
return 0;
}
uint32_t i = 0, n = 0;
while (mnemonic[i]) {
if (mnemonic[i] == ' ') {
n++;
}
i++;
}
n++;
// check number of words
if (n != 12 && n != 18 && n != 24) {
return 0;
}
char current_word[10] = {0};
uint32_t j = 0, k = 0, ki = 0, bi = 0;
uint8_t bits[32 + 1] = {0};
memzero(bits, sizeof(bits));
i = 0;
while (mnemonic[i]) {
j = 0;
while (mnemonic[i] != ' ' && mnemonic[i] != 0) {
if (j >= sizeof(current_word) - 1) {
return 0;
}
current_word[j] = mnemonic[i];
i++;
j++;
}
current_word[j] = 0;
if (mnemonic[i] != 0) {
i++;
}
k = 0;
for (;;) {
if (!wordlist[k]) { // word not found
return 0;
}
if (strcmp(current_word, wordlist[k]) == 0) { // word found on index k
for (ki = 0; ki < 11; ki++) {
if (k & (1 << (10 - ki))) {
bits[bi / 8] |= 1 << (7 - (bi % 8));
}
bi++;
}
break;
}
k++;
}
}
if (bi != n * 11) {
return 0;
}
memcpy(entropy, bits, sizeof(bits));
return n * 11;
}
int mnemonic_check(const char *mnemonic) {
uint8_t bits[32 + 1] = {0};
int seed_len = mnemonic_to_entropy(mnemonic, bits);
if (seed_len != (12 * 11) && seed_len != (18 * 11) && seed_len != (24 * 11)) {
return 0;
}
int words = seed_len / 11;
uint8_t checksum = bits[words * 4 / 3];
sha256_Raw(bits, words * 4 / 3, bits);
if (words == 12) {
return (bits[0] & 0xF0) == (checksum & 0xF0); // compare first 4 bits
} else if (words == 18) {
return (bits[0] & 0xFC) == (checksum & 0xFC); // compare first 6 bits
} else if (words == 24) {
return bits[0] == checksum; // compare 8 bits
}
return 0;
}
// passphrase must be at most 256 characters otherwise it would be truncated
void mnemonic_to_seed(const char *mnemonic, const char *passphrase,
uint8_t seed[512 / 8],
void (*progress_callback)(uint32_t current,
uint32_t total)) {
int mnemoniclen = strlen(mnemonic);
int passphraselen = strnlen(passphrase, 256);
#if USE_BIP39_CACHE
// check cache
if (mnemoniclen < 256 && passphraselen < 64) {
for (int i = 0; i < BIP39_CACHE_SIZE; i++) {
if (!bip39_cache[i].set) continue;
if (strcmp(bip39_cache[i].mnemonic, mnemonic) != 0) continue;
if (strcmp(bip39_cache[i].passphrase, passphrase) != 0) continue;
// found the correct entry
memcpy(seed, bip39_cache[i].seed, 512 / 8);
return;
}
}
#endif
uint8_t salt[8 + 256] = {0};
memcpy(salt, "mnemonic", 8);
memcpy(salt + 8, passphrase, passphraselen);
static CONFIDENTIAL PBKDF2_HMAC_SHA512_CTX pctx;
pbkdf2_hmac_sha512_Init(&pctx, (const uint8_t *)mnemonic, mnemoniclen, salt,
passphraselen + 8, 1);
if (progress_callback) {
progress_callback(0, BIP39_PBKDF2_ROUNDS);
}
for (int i = 0; i < 16; i++) {
pbkdf2_hmac_sha512_Update(&pctx, BIP39_PBKDF2_ROUNDS / 16);
if (progress_callback) {
progress_callback((i + 1) * BIP39_PBKDF2_ROUNDS / 16,
BIP39_PBKDF2_ROUNDS);
}
}
pbkdf2_hmac_sha512_Final(&pctx, seed);
memzero(salt, sizeof(salt));
#if USE_BIP39_CACHE
// store to cache
if (mnemoniclen < 256 && passphraselen < 64) {
bip39_cache[bip39_cache_index].set = true;
strcpy(bip39_cache[bip39_cache_index].mnemonic, mnemonic);
strcpy(bip39_cache[bip39_cache_index].passphrase, passphrase);
memcpy(bip39_cache[bip39_cache_index].seed, seed, 512 / 8);
bip39_cache_index = (bip39_cache_index + 1) % BIP39_CACHE_SIZE;
}
#endif
}
// binary search for finding the word in the wordlist
int mnemonic_find_word(const char *word) {
int lo = 0, hi = BIP39_WORDS - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
int cmp = strcmp(word, wordlist[mid]);
if (cmp == 0) {
return mid;
}
if (cmp > 0) {
lo = mid + 1;
} else {
hi = mid - 1;
}
}
return -1;
}
const char *mnemonic_complete_word(const char *prefix, int len) {
// we need to perform linear search,
// because we want to return the first match
for (const char *const *w = wordlist; *w != 0; w++) {
if (strncmp(*w, prefix, len) == 0) {
return *w;
}
}
return NULL;
}
const char *mnemonic_get_word(int index) {
if (index >= 0 && index < BIP39_WORDS) {
return wordlist[index];
} else {
return NULL;
}
}
uint32_t mnemonic_word_completion_mask(const char *prefix, int len) {
if (len <= 0) {
return 0x3ffffff; // all letters (bits 1-26 set)
}
uint32_t res = 0;
for (const char *const *w = wordlist; *w != 0; w++) {
const char *word = *w;
if (strncmp(word, prefix, len) == 0 && word[len] >= 'a' &&
word[len] <= 'z') {
res |= 1 << (word[len] - 'a');
}
}
return res;
}

52
src/crypto/bip39/bip39.h Normal file
View File

@@ -0,0 +1,52 @@
/**
* Copyright (c) 2013-2014 Tomas Dzetkulic
* Copyright (c) 2013-2014 Pavol Rusnak
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __BIP39_H__
#define __BIP39_H__
#include <stdbool.h>
#include <stdint.h>
#define BIP39_WORDS 2048
#define BIP39_PBKDF2_ROUNDS 2048
const char *mnemonic_generate(int strength); // strength in bits
const char *mnemonic_from_data(const uint8_t *data, int len);
void mnemonic_clear(void);
int mnemonic_check(const char *mnemonic);
int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy);
// passphrase must be at most 256 characters otherwise it would be truncated
void mnemonic_to_seed(const char *mnemonic, const char *passphrase,
uint8_t seed[512 / 8],
void (*progress_callback)(uint32_t current,
uint32_t total));
int mnemonic_find_word(const char *word);
const char *mnemonic_complete_word(const char *prefix, int len);
const char *mnemonic_get_word(int index);
uint32_t mnemonic_word_completion_mask(const char *prefix, int len);
#endif

View File

@@ -0,0 +1,367 @@
/**
* Copyright (c) 2013-2014 Tomas Dzetkulic
* Copyright (c) 2013-2014 Pavol Rusnak
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
static const char* const wordlist[] = {
"abandon", "ability", "able", "about", "above", "absent",
"absorb", "abstract", "absurd", "abuse", "access", "accident",
"account", "accuse", "achieve", "acid", "acoustic", "acquire",
"across", "act", "action", "actor", "actress", "actual",
"adapt", "add", "addict", "address", "adjust", "admit",
"adult", "advance", "advice", "aerobic", "affair", "afford",
"afraid", "again", "age", "agent", "agree", "ahead",
"aim", "air", "airport", "aisle", "alarm", "album",
"alcohol", "alert", "alien", "all", "alley", "allow",
"almost", "alone", "alpha", "already", "also", "alter",
"always", "amateur", "amazing", "among", "amount", "amused",
"analyst", "anchor", "ancient", "anger", "angle", "angry",
"animal", "ankle", "announce", "annual", "another", "answer",
"antenna", "antique", "anxiety", "any", "apart", "apology",
"appear", "apple", "approve", "april", "arch", "arctic",
"area", "arena", "argue", "arm", "armed", "armor",
"army", "around", "arrange", "arrest", "arrive", "arrow",
"art", "artefact", "artist", "artwork", "ask", "aspect",
"assault", "asset", "assist", "assume", "asthma", "athlete",
"atom", "attack", "attend", "attitude", "attract", "auction",
"audit", "august", "aunt", "author", "auto", "autumn",
"average", "avocado", "avoid", "awake", "aware", "away",
"awesome", "awful", "awkward", "axis", "baby", "bachelor",
"bacon", "badge", "bag", "balance", "balcony", "ball",
"bamboo", "banana", "banner", "bar", "barely", "bargain",
"barrel", "base", "basic", "basket", "battle", "beach",
"bean", "beauty", "because", "become", "beef", "before",
"begin", "behave", "behind", "believe", "below", "belt",
"bench", "benefit", "best", "betray", "better", "between",
"beyond", "bicycle", "bid", "bike", "bind", "biology",
"bird", "birth", "bitter", "black", "blade", "blame",
"blanket", "blast", "bleak", "bless", "blind", "blood",
"blossom", "blouse", "blue", "blur", "blush", "board",
"boat", "body", "boil", "bomb", "bone", "bonus",
"book", "boost", "border", "boring", "borrow", "boss",
"bottom", "bounce", "box", "boy", "bracket", "brain",
"brand", "brass", "brave", "bread", "breeze", "brick",
"bridge", "brief", "bright", "bring", "brisk", "broccoli",
"broken", "bronze", "broom", "brother", "brown", "brush",
"bubble", "buddy", "budget", "buffalo", "build", "bulb",
"bulk", "bullet", "bundle", "bunker", "burden", "burger",
"burst", "bus", "business", "busy", "butter", "buyer",
"buzz", "cabbage", "cabin", "cable", "cactus", "cage",
"cake", "call", "calm", "camera", "camp", "can",
"canal", "cancel", "candy", "cannon", "canoe", "canvas",
"canyon", "capable", "capital", "captain", "car", "carbon",
"card", "cargo", "carpet", "carry", "cart", "case",
"cash", "casino", "castle", "casual", "cat", "catalog",
"catch", "category", "cattle", "caught", "cause", "caution",
"cave", "ceiling", "celery", "cement", "census", "century",
"cereal", "certain", "chair", "chalk", "champion", "change",
"chaos", "chapter", "charge", "chase", "chat", "cheap",
"check", "cheese", "chef", "cherry", "chest", "chicken",
"chief", "child", "chimney", "choice", "choose", "chronic",
"chuckle", "chunk", "churn", "cigar", "cinnamon", "circle",
"citizen", "city", "civil", "claim", "clap", "clarify",
"claw", "clay", "clean", "clerk", "clever", "click",
"client", "cliff", "climb", "clinic", "clip", "clock",
"clog", "close", "cloth", "cloud", "clown", "club",
"clump", "cluster", "clutch", "coach", "coast", "coconut",
"code", "coffee", "coil", "coin", "collect", "color",
"column", "combine", "come", "comfort", "comic", "common",
"company", "concert", "conduct", "confirm", "congress", "connect",
"consider", "control", "convince", "cook", "cool", "copper",
"copy", "coral", "core", "corn", "correct", "cost",
"cotton", "couch", "country", "couple", "course", "cousin",
"cover", "coyote", "crack", "cradle", "craft", "cram",
"crane", "crash", "crater", "crawl", "crazy", "cream",
"credit", "creek", "crew", "cricket", "crime", "crisp",
"critic", "crop", "cross", "crouch", "crowd", "crucial",
"cruel", "cruise", "crumble", "crunch", "crush", "cry",
"crystal", "cube", "culture", "cup", "cupboard", "curious",
"current", "curtain", "curve", "cushion", "custom", "cute",
"cycle", "dad", "damage", "damp", "dance", "danger",
"daring", "dash", "daughter", "dawn", "day", "deal",
"debate", "debris", "decade", "december", "decide", "decline",
"decorate", "decrease", "deer", "defense", "define", "defy",
"degree", "delay", "deliver", "demand", "demise", "denial",
"dentist", "deny", "depart", "depend", "deposit", "depth",
"deputy", "derive", "describe", "desert", "design", "desk",
"despair", "destroy", "detail", "detect", "develop", "device",
"devote", "diagram", "dial", "diamond", "diary", "dice",
"diesel", "diet", "differ", "digital", "dignity", "dilemma",
"dinner", "dinosaur", "direct", "dirt", "disagree", "discover",
"disease", "dish", "dismiss", "disorder", "display", "distance",
"divert", "divide", "divorce", "dizzy", "doctor", "document",
"dog", "doll", "dolphin", "domain", "donate", "donkey",
"donor", "door", "dose", "double", "dove", "draft",
"dragon", "drama", "drastic", "draw", "dream", "dress",
"drift", "drill", "drink", "drip", "drive", "drop",
"drum", "dry", "duck", "dumb", "dune", "during",
"dust", "dutch", "duty", "dwarf", "dynamic", "eager",
"eagle", "early", "earn", "earth", "easily", "east",
"easy", "echo", "ecology", "economy", "edge", "edit",
"educate", "effort", "egg", "eight", "either", "elbow",
"elder", "electric", "elegant", "element", "elephant", "elevator",
"elite", "else", "embark", "embody", "embrace", "emerge",
"emotion", "employ", "empower", "empty", "enable", "enact",
"end", "endless", "endorse", "enemy", "energy", "enforce",
"engage", "engine", "enhance", "enjoy", "enlist", "enough",
"enrich", "enroll", "ensure", "enter", "entire", "entry",
"envelope", "episode", "equal", "equip", "era", "erase",
"erode", "erosion", "error", "erupt", "escape", "essay",
"essence", "estate", "eternal", "ethics", "evidence", "evil",
"evoke", "evolve", "exact", "example", "excess", "exchange",
"excite", "exclude", "excuse", "execute", "exercise", "exhaust",
"exhibit", "exile", "exist", "exit", "exotic", "expand",
"expect", "expire", "explain", "expose", "express", "extend",
"extra", "eye", "eyebrow", "fabric", "face", "faculty",
"fade", "faint", "faith", "fall", "false", "fame",
"family", "famous", "fan", "fancy", "fantasy", "farm",
"fashion", "fat", "fatal", "father", "fatigue", "fault",
"favorite", "feature", "february", "federal", "fee", "feed",
"feel", "female", "fence", "festival", "fetch", "fever",
"few", "fiber", "fiction", "field", "figure", "file",
"film", "filter", "final", "find", "fine", "finger",
"finish", "fire", "firm", "first", "fiscal", "fish",
"fit", "fitness", "fix", "flag", "flame", "flash",
"flat", "flavor", "flee", "flight", "flip", "float",
"flock", "floor", "flower", "fluid", "flush", "fly",
"foam", "focus", "fog", "foil", "fold", "follow",
"food", "foot", "force", "forest", "forget", "fork",
"fortune", "forum", "forward", "fossil", "foster", "found",
"fox", "fragile", "frame", "frequent", "fresh", "friend",
"fringe", "frog", "front", "frost", "frown", "frozen",
"fruit", "fuel", "fun", "funny", "furnace", "fury",
"future", "gadget", "gain", "galaxy", "gallery", "game",
"gap", "garage", "garbage", "garden", "garlic", "garment",
"gas", "gasp", "gate", "gather", "gauge", "gaze",
"general", "genius", "genre", "gentle", "genuine", "gesture",
"ghost", "giant", "gift", "giggle", "ginger", "giraffe",
"girl", "give", "glad", "glance", "glare", "glass",
"glide", "glimpse", "globe", "gloom", "glory", "glove",
"glow", "glue", "goat", "goddess", "gold", "good",
"goose", "gorilla", "gospel", "gossip", "govern", "gown",
"grab", "grace", "grain", "grant", "grape", "grass",
"gravity", "great", "green", "grid", "grief", "grit",
"grocery", "group", "grow", "grunt", "guard", "guess",
"guide", "guilt", "guitar", "gun", "gym", "habit",
"hair", "half", "hammer", "hamster", "hand", "happy",
"harbor", "hard", "harsh", "harvest", "hat", "have",
"hawk", "hazard", "head", "health", "heart", "heavy",
"hedgehog", "height", "hello", "helmet", "help", "hen",
"hero", "hidden", "high", "hill", "hint", "hip",
"hire", "history", "hobby", "hockey", "hold", "hole",
"holiday", "hollow", "home", "honey", "hood", "hope",
"horn", "horror", "horse", "hospital", "host", "hotel",
"hour", "hover", "hub", "huge", "human", "humble",
"humor", "hundred", "hungry", "hunt", "hurdle", "hurry",
"hurt", "husband", "hybrid", "ice", "icon", "idea",
"identify", "idle", "ignore", "ill", "illegal", "illness",
"image", "imitate", "immense", "immune", "impact", "impose",
"improve", "impulse", "inch", "include", "income", "increase",
"index", "indicate", "indoor", "industry", "infant", "inflict",
"inform", "inhale", "inherit", "initial", "inject", "injury",
"inmate", "inner", "innocent", "input", "inquiry", "insane",
"insect", "inside", "inspire", "install", "intact", "interest",
"into", "invest", "invite", "involve", "iron", "island",
"isolate", "issue", "item", "ivory", "jacket", "jaguar",
"jar", "jazz", "jealous", "jeans", "jelly", "jewel",
"job", "join", "joke", "journey", "joy", "judge",
"juice", "jump", "jungle", "junior", "junk", "just",
"kangaroo", "keen", "keep", "ketchup", "key", "kick",
"kid", "kidney", "kind", "kingdom", "kiss", "kit",
"kitchen", "kite", "kitten", "kiwi", "knee", "knife",
"knock", "know", "lab", "label", "labor", "ladder",
"lady", "lake", "lamp", "language", "laptop", "large",
"later", "latin", "laugh", "laundry", "lava", "law",
"lawn", "lawsuit", "layer", "lazy", "leader", "leaf",
"learn", "leave", "lecture", "left", "leg", "legal",
"legend", "leisure", "lemon", "lend", "length", "lens",
"leopard", "lesson", "letter", "level", "liar", "liberty",
"library", "license", "life", "lift", "light", "like",
"limb", "limit", "link", "lion", "liquid", "list",
"little", "live", "lizard", "load", "loan", "lobster",
"local", "lock", "logic", "lonely", "long", "loop",
"lottery", "loud", "lounge", "love", "loyal", "lucky",
"luggage", "lumber", "lunar", "lunch", "luxury", "lyrics",
"machine", "mad", "magic", "magnet", "maid", "mail",
"main", "major", "make", "mammal", "man", "manage",
"mandate", "mango", "mansion", "manual", "maple", "marble",
"march", "margin", "marine", "market", "marriage", "mask",
"mass", "master", "match", "material", "math", "matrix",
"matter", "maximum", "maze", "meadow", "mean", "measure",
"meat", "mechanic", "medal", "media", "melody", "melt",
"member", "memory", "mention", "menu", "mercy", "merge",
"merit", "merry", "mesh", "message", "metal", "method",
"middle", "midnight", "milk", "million", "mimic", "mind",
"minimum", "minor", "minute", "miracle", "mirror", "misery",
"miss", "mistake", "mix", "mixed", "mixture", "mobile",
"model", "modify", "mom", "moment", "monitor", "monkey",
"monster", "month", "moon", "moral", "more", "morning",
"mosquito", "mother", "motion", "motor", "mountain", "mouse",
"move", "movie", "much", "muffin", "mule", "multiply",
"muscle", "museum", "mushroom", "music", "must", "mutual",
"myself", "mystery", "myth", "naive", "name", "napkin",
"narrow", "nasty", "nation", "nature", "near", "neck",
"need", "negative", "neglect", "neither", "nephew", "nerve",
"nest", "net", "network", "neutral", "never", "news",
"next", "nice", "night", "noble", "noise", "nominee",
"noodle", "normal", "north", "nose", "notable", "note",
"nothing", "notice", "novel", "now", "nuclear", "number",
"nurse", "nut", "oak", "obey", "object", "oblige",
"obscure", "observe", "obtain", "obvious", "occur", "ocean",
"october", "odor", "off", "offer", "office", "often",
"oil", "okay", "old", "olive", "olympic", "omit",
"once", "one", "onion", "online", "only", "open",
"opera", "opinion", "oppose", "option", "orange", "orbit",
"orchard", "order", "ordinary", "organ", "orient", "original",
"orphan", "ostrich", "other", "outdoor", "outer", "output",
"outside", "oval", "oven", "over", "own", "owner",
"oxygen", "oyster", "ozone", "pact", "paddle", "page",
"pair", "palace", "palm", "panda", "panel", "panic",
"panther", "paper", "parade", "parent", "park", "parrot",
"party", "pass", "patch", "path", "patient", "patrol",
"pattern", "pause", "pave", "payment", "peace", "peanut",
"pear", "peasant", "pelican", "pen", "penalty", "pencil",
"people", "pepper", "perfect", "permit", "person", "pet",
"phone", "photo", "phrase", "physical", "piano", "picnic",
"picture", "piece", "pig", "pigeon", "pill", "pilot",
"pink", "pioneer", "pipe", "pistol", "pitch", "pizza",
"place", "planet", "plastic", "plate", "play", "please",
"pledge", "pluck", "plug", "plunge", "poem", "poet",
"point", "polar", "pole", "police", "pond", "pony",
"pool", "popular", "portion", "position", "possible", "post",
"potato", "pottery", "poverty", "powder", "power", "practice",
"praise", "predict", "prefer", "prepare", "present", "pretty",
"prevent", "price", "pride", "primary", "print", "priority",
"prison", "private", "prize", "problem", "process", "produce",
"profit", "program", "project", "promote", "proof", "property",
"prosper", "protect", "proud", "provide", "public", "pudding",
"pull", "pulp", "pulse", "pumpkin", "punch", "pupil",
"puppy", "purchase", "purity", "purpose", "purse", "push",
"put", "puzzle", "pyramid", "quality", "quantum", "quarter",
"question", "quick", "quit", "quiz", "quote", "rabbit",
"raccoon", "race", "rack", "radar", "radio", "rail",
"rain", "raise", "rally", "ramp", "ranch", "random",
"range", "rapid", "rare", "rate", "rather", "raven",
"raw", "razor", "ready", "real", "reason", "rebel",
"rebuild", "recall", "receive", "recipe", "record", "recycle",
"reduce", "reflect", "reform", "refuse", "region", "regret",
"regular", "reject", "relax", "release", "relief", "rely",
"remain", "remember", "remind", "remove", "render", "renew",
"rent", "reopen", "repair", "repeat", "replace", "report",
"require", "rescue", "resemble", "resist", "resource", "response",
"result", "retire", "retreat", "return", "reunion", "reveal",
"review", "reward", "rhythm", "rib", "ribbon", "rice",
"rich", "ride", "ridge", "rifle", "right", "rigid",
"ring", "riot", "ripple", "risk", "ritual", "rival",
"river", "road", "roast", "robot", "robust", "rocket",
"romance", "roof", "rookie", "room", "rose", "rotate",
"rough", "round", "route", "royal", "rubber", "rude",
"rug", "rule", "run", "runway", "rural", "sad",
"saddle", "sadness", "safe", "sail", "salad", "salmon",
"salon", "salt", "salute", "same", "sample", "sand",
"satisfy", "satoshi", "sauce", "sausage", "save", "say",
"scale", "scan", "scare", "scatter", "scene", "scheme",
"school", "science", "scissors", "scorpion", "scout", "scrap",
"screen", "script", "scrub", "sea", "search", "season",
"seat", "second", "secret", "section", "security", "seed",
"seek", "segment", "select", "sell", "seminar", "senior",
"sense", "sentence", "series", "service", "session", "settle",
"setup", "seven", "shadow", "shaft", "shallow", "share",
"shed", "shell", "sheriff", "shield", "shift", "shine",
"ship", "shiver", "shock", "shoe", "shoot", "shop",
"short", "shoulder", "shove", "shrimp", "shrug", "shuffle",
"shy", "sibling", "sick", "side", "siege", "sight",
"sign", "silent", "silk", "silly", "silver", "similar",
"simple", "since", "sing", "siren", "sister", "situate",
"six", "size", "skate", "sketch", "ski", "skill",
"skin", "skirt", "skull", "slab", "slam", "sleep",
"slender", "slice", "slide", "slight", "slim", "slogan",
"slot", "slow", "slush", "small", "smart", "smile",
"smoke", "smooth", "snack", "snake", "snap", "sniff",
"snow", "soap", "soccer", "social", "sock", "soda",
"soft", "solar", "soldier", "solid", "solution", "solve",
"someone", "song", "soon", "sorry", "sort", "soul",
"sound", "soup", "source", "south", "space", "spare",
"spatial", "spawn", "speak", "special", "speed", "spell",
"spend", "sphere", "spice", "spider", "spike", "spin",
"spirit", "split", "spoil", "sponsor", "spoon", "sport",
"spot", "spray", "spread", "spring", "spy", "square",
"squeeze", "squirrel", "stable", "stadium", "staff", "stage",
"stairs", "stamp", "stand", "start", "state", "stay",
"steak", "steel", "stem", "step", "stereo", "stick",
"still", "sting", "stock", "stomach", "stone", "stool",
"story", "stove", "strategy", "street", "strike", "strong",
"struggle", "student", "stuff", "stumble", "style", "subject",
"submit", "subway", "success", "such", "sudden", "suffer",
"sugar", "suggest", "suit", "summer", "sun", "sunny",
"sunset", "super", "supply", "supreme", "sure", "surface",
"surge", "surprise", "surround", "survey", "suspect", "sustain",
"swallow", "swamp", "swap", "swarm", "swear", "sweet",
"swift", "swim", "swing", "switch", "sword", "symbol",
"symptom", "syrup", "system", "table", "tackle", "tag",
"tail", "talent", "talk", "tank", "tape", "target",
"task", "taste", "tattoo", "taxi", "teach", "team",
"tell", "ten", "tenant", "tennis", "tent", "term",
"test", "text", "thank", "that", "theme", "then",
"theory", "there", "they", "thing", "this", "thought",
"three", "thrive", "throw", "thumb", "thunder", "ticket",
"tide", "tiger", "tilt", "timber", "time", "tiny",
"tip", "tired", "tissue", "title", "toast", "tobacco",
"today", "toddler", "toe", "together", "toilet", "token",
"tomato", "tomorrow", "tone", "tongue", "tonight", "tool",
"tooth", "top", "topic", "topple", "torch", "tornado",
"tortoise", "toss", "total", "tourist", "toward", "tower",
"town", "toy", "track", "trade", "traffic", "tragic",
"train", "transfer", "trap", "trash", "travel", "tray",
"treat", "tree", "trend", "trial", "tribe", "trick",
"trigger", "trim", "trip", "trophy", "trouble", "truck",
"true", "truly", "trumpet", "trust", "truth", "try",
"tube", "tuition", "tumble", "tuna", "tunnel", "turkey",
"turn", "turtle", "twelve", "twenty", "twice", "twin",
"twist", "two", "type", "typical", "ugly", "umbrella",
"unable", "unaware", "uncle", "uncover", "under", "undo",
"unfair", "unfold", "unhappy", "uniform", "unique", "unit",
"universe", "unknown", "unlock", "until", "unusual", "unveil",
"update", "upgrade", "uphold", "upon", "upper", "upset",
"urban", "urge", "usage", "use", "used", "useful",
"useless", "usual", "utility", "vacant", "vacuum", "vague",
"valid", "valley", "valve", "van", "vanish", "vapor",
"various", "vast", "vault", "vehicle", "velvet", "vendor",
"venture", "venue", "verb", "verify", "version", "very",
"vessel", "veteran", "viable", "vibrant", "vicious", "victory",
"video", "view", "village", "vintage", "violin", "virtual",
"virus", "visa", "visit", "visual", "vital", "vivid",
"vocal", "voice", "void", "volcano", "volume", "vote",
"voyage", "wage", "wagon", "wait", "walk", "wall",
"walnut", "want", "warfare", "warm", "warrior", "wash",
"wasp", "waste", "water", "wave", "way", "wealth",
"weapon", "wear", "weasel", "weather", "web", "wedding",
"weekend", "weird", "welcome", "west", "wet", "whale",
"what", "wheat", "wheel", "when", "where", "whip",
"whisper", "wide", "width", "wife", "wild", "will",
"win", "window", "wine", "wing", "wink", "winner",
"winter", "wire", "wisdom", "wise", "wish", "witness",
"wolf", "woman", "wonder", "wood", "wool", "word",
"work", "world", "worry", "worth", "wrap", "wreck",
"wrestle", "wrist", "write", "wrong", "yard", "year",
"yellow", "you", "young", "youth", "zebra", "zero",
"zone", "zoo", 0,
};

176
src/crypto/bip39/hmac.c Normal file
View File

@@ -0,0 +1,176 @@
/**
* Copyright (c) 2013-2014 Tomas Dzetkulic
* Copyright (c) 2013-2014 Pavol Rusnak
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#include "hmac.h"
#include "memzero.h"
#include "options.h"
void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key,
const uint32_t keylen) {
static CONFIDENTIAL uint8_t i_key_pad[SHA256_BLOCK_LENGTH];
memzero(i_key_pad, SHA256_BLOCK_LENGTH);
if (keylen > SHA256_BLOCK_LENGTH) {
sha256_Raw(key, keylen, i_key_pad);
} else {
memcpy(i_key_pad, key, keylen);
}
for (int i = 0; i < SHA256_BLOCK_LENGTH; i++) {
hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c;
i_key_pad[i] ^= 0x36;
}
sha256_Init(&(hctx->ctx));
sha256_Update(&(hctx->ctx), i_key_pad, SHA256_BLOCK_LENGTH);
memzero(i_key_pad, sizeof(i_key_pad));
}
void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg,
const uint32_t msglen) {
sha256_Update(&(hctx->ctx), msg, msglen);
}
void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac) {
sha256_Final(&(hctx->ctx), hmac);
sha256_Init(&(hctx->ctx));
sha256_Update(&(hctx->ctx), hctx->o_key_pad, SHA256_BLOCK_LENGTH);
sha256_Update(&(hctx->ctx), hmac, SHA256_DIGEST_LENGTH);
sha256_Final(&(hctx->ctx), hmac);
memzero(hctx, sizeof(HMAC_SHA256_CTX));
}
void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
const uint32_t msglen, uint8_t *hmac) {
static CONFIDENTIAL HMAC_SHA256_CTX hctx;
hmac_sha256_Init(&hctx, key, keylen);
hmac_sha256_Update(&hctx, msg, msglen);
hmac_sha256_Final(&hctx, hmac);
}
void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen,
uint32_t *opad_digest, uint32_t *ipad_digest) {
static CONFIDENTIAL uint32_t key_pad[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];
memzero(key_pad, sizeof(key_pad));
if (keylen > SHA256_BLOCK_LENGTH) {
static CONFIDENTIAL SHA256_CTX context;
sha256_Init(&context);
sha256_Update(&context, key, keylen);
sha256_Final(&context, (uint8_t *)key_pad);
} else {
memcpy(key_pad, key, keylen);
}
/* compute o_key_pad and its digest */
for (int i = 0; i < SHA256_BLOCK_LENGTH / (int)sizeof(uint32_t); i++) {
uint32_t data = 0;
#if BYTE_ORDER == LITTLE_ENDIAN
REVERSE32(key_pad[i], data);
#else
data = key_pad[i];
#endif
key_pad[i] = data ^ 0x5c5c5c5c;
}
sha256_Transform(sha256_initial_hash_value, key_pad, opad_digest);
/* convert o_key_pad to i_key_pad and compute its digest */
for (int i = 0; i < SHA256_BLOCK_LENGTH / (int)sizeof(uint32_t); i++) {
key_pad[i] = key_pad[i] ^ 0x5c5c5c5c ^ 0x36363636;
}
sha256_Transform(sha256_initial_hash_value, key_pad, ipad_digest);
memzero(key_pad, sizeof(key_pad));
}
void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key,
const uint32_t keylen) {
static CONFIDENTIAL uint8_t i_key_pad[SHA512_BLOCK_LENGTH];
memzero(i_key_pad, SHA512_BLOCK_LENGTH);
if (keylen > SHA512_BLOCK_LENGTH) {
sha512_Raw(key, keylen, i_key_pad);
} else {
memcpy(i_key_pad, key, keylen);
}
for (int i = 0; i < SHA512_BLOCK_LENGTH; i++) {
hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c;
i_key_pad[i] ^= 0x36;
}
sha512_Init(&(hctx->ctx));
sha512_Update(&(hctx->ctx), i_key_pad, SHA512_BLOCK_LENGTH);
memzero(i_key_pad, sizeof(i_key_pad));
}
void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg,
const uint32_t msglen) {
sha512_Update(&(hctx->ctx), msg, msglen);
}
void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac) {
sha512_Final(&(hctx->ctx), hmac);
sha512_Init(&(hctx->ctx));
sha512_Update(&(hctx->ctx), hctx->o_key_pad, SHA512_BLOCK_LENGTH);
sha512_Update(&(hctx->ctx), hmac, SHA512_DIGEST_LENGTH);
sha512_Final(&(hctx->ctx), hmac);
memzero(hctx, sizeof(HMAC_SHA512_CTX));
}
void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
const uint32_t msglen, uint8_t *hmac) {
HMAC_SHA512_CTX hctx = {0};
hmac_sha512_Init(&hctx, key, keylen);
hmac_sha512_Update(&hctx, msg, msglen);
hmac_sha512_Final(&hctx, hmac);
}
void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen,
uint64_t *opad_digest, uint64_t *ipad_digest) {
static CONFIDENTIAL uint64_t key_pad[SHA512_BLOCK_LENGTH / sizeof(uint64_t)];
memzero(key_pad, sizeof(key_pad));
if (keylen > SHA512_BLOCK_LENGTH) {
static CONFIDENTIAL SHA512_CTX context;
sha512_Init(&context);
sha512_Update(&context, key, keylen);
sha512_Final(&context, (uint8_t *)key_pad);
} else {
memcpy(key_pad, key, keylen);
}
/* compute o_key_pad and its digest */
for (int i = 0; i < SHA512_BLOCK_LENGTH / (int)sizeof(uint64_t); i++) {
uint64_t data = 0;
#if BYTE_ORDER == LITTLE_ENDIAN
REVERSE64(key_pad[i], data);
#else
data = key_pad[i];
#endif
key_pad[i] = data ^ 0x5c5c5c5c5c5c5c5c;
}
sha512_Transform(sha512_initial_hash_value, key_pad, opad_digest);
/* convert o_key_pad to i_key_pad and compute its digest */
for (int i = 0; i < SHA512_BLOCK_LENGTH / (int)sizeof(uint64_t); i++) {
key_pad[i] = key_pad[i] ^ 0x5c5c5c5c5c5c5c5c ^ 0x3636363636363636;
}
sha512_Transform(sha512_initial_hash_value, key_pad, ipad_digest);
memzero(key_pad, sizeof(key_pad));
}

60
src/crypto/bip39/hmac.h Normal file
View File

@@ -0,0 +1,60 @@
/**
* Copyright (c) 2013-2014 Tomas Dzetkulic
* Copyright (c) 2013-2014 Pavol Rusnak
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT HMAC_SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __HMAC_H__
#define __HMAC_H__
#include <stdint.h>
#include "sha2.h"
typedef struct _HMAC_SHA256_CTX {
uint8_t o_key_pad[SHA256_BLOCK_LENGTH];
SHA256_CTX ctx;
} HMAC_SHA256_CTX;
typedef struct _HMAC_SHA512_CTX {
uint8_t o_key_pad[SHA512_BLOCK_LENGTH];
SHA512_CTX ctx;
} HMAC_SHA512_CTX;
void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key,
const uint32_t keylen);
void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg,
const uint32_t msglen);
void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac);
void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
const uint32_t msglen, uint8_t *hmac);
void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen,
uint32_t *opad_digest, uint32_t *ipad_digest);
void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key,
const uint32_t keylen);
void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg,
const uint32_t msglen);
void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac);
void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
const uint32_t msglen, uint8_t *hmac);
void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen,
uint64_t *opad_digest, uint64_t *ipad_digest);
#endif

View File

@@ -0,0 +1,130 @@
/**
* Copyright (c) 2019 Andrew R. Kozlik
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "hmac_drbg.h"
#include <string.h>
#include "memzero.h"
#include "sha2.h"
static void update_k(HMAC_DRBG_CTX *ctx, uint8_t domain, const uint8_t *data1,
size_t len1, const uint8_t *data2, size_t len2) {
// Computes K = HMAC(K, V || domain || data1 || data 2).
// First hash operation of HMAC.
uint32_t h[SHA256_BLOCK_LENGTH / sizeof(uint32_t)] = {0};
if (len1 + len2 == 0) {
ctx->v[8] = 0x00800000;
ctx->v[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH + 1) * 8;
sha256_Transform(ctx->idig, ctx->v, h);
ctx->v[8] = 0x80000000;
ctx->v[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
} else {
SHA256_CTX sha_ctx = {0};
memcpy(sha_ctx.state, ctx->idig, SHA256_DIGEST_LENGTH);
for (size_t i = 0; i < SHA256_DIGEST_LENGTH / sizeof(uint32_t); i++) {
#if BYTE_ORDER == LITTLE_ENDIAN
REVERSE32(ctx->v[i], sha_ctx.buffer[i]);
#else
sha_ctx.buffer[i] = ctx->v[i];
#endif
}
((uint8_t *)sha_ctx.buffer)[SHA256_DIGEST_LENGTH] = domain;
sha_ctx.bitcount = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH + 1) * 8;
sha256_Update(&sha_ctx, data1, len1);
sha256_Update(&sha_ctx, data2, len2);
sha256_Final(&sha_ctx, (uint8_t *)h);
#if BYTE_ORDER == LITTLE_ENDIAN
for (size_t i = 0; i < SHA256_DIGEST_LENGTH / sizeof(uint32_t); i++)
REVERSE32(h[i], h[i]);
#endif
}
// Second hash operation of HMAC.
h[8] = 0x80000000;
h[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
sha256_Transform(ctx->odig, h, h);
// Precompute the inner digest and outer digest of K.
h[8] = 0;
h[15] = 0;
for (size_t i = 0; i < SHA256_BLOCK_LENGTH / sizeof(uint32_t); i++) {
h[i] ^= 0x36363636;
}
sha256_Transform(sha256_initial_hash_value, h, ctx->idig);
for (size_t i = 0; i < SHA256_BLOCK_LENGTH / sizeof(uint32_t); i++) {
h[i] = h[i] ^ 0x36363636 ^ 0x5c5c5c5c;
}
sha256_Transform(sha256_initial_hash_value, h, ctx->odig);
memzero(h, sizeof(h));
}
static void update_v(HMAC_DRBG_CTX *ctx) {
sha256_Transform(ctx->idig, ctx->v, ctx->v);
sha256_Transform(ctx->odig, ctx->v, ctx->v);
}
void hmac_drbg_init(HMAC_DRBG_CTX *ctx, const uint8_t *entropy,
size_t entropy_len, const uint8_t *nonce,
size_t nonce_len) {
uint32_t h[SHA256_BLOCK_LENGTH / sizeof(uint32_t)] = {0};
// Precompute the inner digest and outer digest of K = 0x00 ... 0x00.
memset(h, 0x36, sizeof(h));
sha256_Transform(sha256_initial_hash_value, h, ctx->idig);
memset(h, 0x5c, sizeof(h));
sha256_Transform(sha256_initial_hash_value, h, ctx->odig);
// Let V = 0x01 ... 0x01.
memset(ctx->v, 1, SHA256_DIGEST_LENGTH);
for (size_t i = 9; i < 15; i++) ctx->v[i] = 0;
ctx->v[8] = 0x80000000;
ctx->v[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
hmac_drbg_reseed(ctx, entropy, entropy_len, nonce, nonce_len);
memzero(h, sizeof(h));
}
void hmac_drbg_reseed(HMAC_DRBG_CTX *ctx, const uint8_t *entropy, size_t len,
const uint8_t *addin, size_t addin_len) {
update_k(ctx, 0, entropy, len, addin, addin_len);
update_v(ctx);
if (len == 0) return;
update_k(ctx, 1, entropy, len, addin, addin_len);
update_v(ctx);
}
void hmac_drbg_generate(HMAC_DRBG_CTX *ctx, uint8_t *buf, size_t len) {
size_t i = 0;
while (i < len) {
update_v(ctx);
for (size_t j = 0; j < 8 && i < len; j++) {
uint32_t r = ctx->v[j];
for (int k = 24; k >= 0 && i < len; k -= 8) {
buf[i++] = (r >> k) & 0xFF;
}
}
}
update_k(ctx, 0, NULL, 0, NULL, 0);
update_v(ctx);
}

View File

@@ -0,0 +1,43 @@
/**
* Copyright (c) 2019 Andrew R. Kozlik
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __HMAC_DRBG_H__
#define __HMAC_DRBG_H__
#include <sha2.h>
#include <stdint.h>
// HMAC based Deterministic Random Bit Generator with SHA-256
typedef struct _HMAC_DRBG_CTX {
uint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
uint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
uint32_t v[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];
} HMAC_DRBG_CTX;
void hmac_drbg_init(HMAC_DRBG_CTX *ctx, const uint8_t *buf, size_t len,
const uint8_t *nonce, size_t nonce_len);
void hmac_drbg_reseed(HMAC_DRBG_CTX *ctx, const uint8_t *buf, size_t len,
const uint8_t *addin, size_t addin_len);
void hmac_drbg_generate(HMAC_DRBG_CTX *ctx, uint8_t *buf, size_t len);
#endif

View File

@@ -0,0 +1,8 @@
#ifndef __MEMZERO_H__
#define __MEMZERO_H__
#include <stddef.h>
void memzero(void* const pnt, const size_t len);
#endif

View File

@@ -0,0 +1,99 @@
/**
* Copyright (c) 2013-2014 Pavol Rusnak
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __OPTIONS_H__
#define __OPTIONS_H__
// use precomputed Curve Points (some scalar multiples of curve base point G)
#ifndef USE_PRECOMPUTED_CP
#define USE_PRECOMPUTED_CP 1
#endif
// use fast inverse method
#ifndef USE_INVERSE_FAST
#define USE_INVERSE_FAST 1
#endif
// support for printing bignum256 structures via printf
#ifndef USE_BN_PRINT
#define USE_BN_PRINT 0
#endif
// use deterministic signatures
#ifndef USE_RFC6979
#define USE_RFC6979 1
#endif
// implement BIP32 caching
#ifndef USE_BIP32_CACHE
#define USE_BIP32_CACHE 1
#define BIP32_CACHE_SIZE 10
#define BIP32_CACHE_MAXDEPTH 8
#endif
// support constructing BIP32 nodes from ed25519 and curve25519 curves.
#ifndef USE_BIP32_25519_CURVES
#define USE_BIP32_25519_CURVES 1
#endif
// implement BIP39 caching
#ifndef USE_BIP39_CACHE
#define USE_BIP39_CACHE 1
#define BIP39_CACHE_SIZE 4
#endif
// support Ethereum operations
#ifndef USE_ETHEREUM
#define USE_ETHEREUM 0
#endif
// support Graphene operations (STEEM, BitShares)
#ifndef USE_GRAPHENE
#define USE_GRAPHENE 0
#endif
// support NEM operations
#ifndef USE_NEM
#define USE_NEM 0
#endif
// support MONERO operations
#ifndef USE_MONERO
#define USE_MONERO 0
#endif
// support CARDANO operations
#ifndef USE_CARDANO
#define USE_CARDANO 0
#endif
// support Keccak hashing
#ifndef USE_KECCAK
#define USE_KECCAK 1
#endif
// add way how to mark confidential data
#ifndef CONFIDENTIAL
#define CONFIDENTIAL
#endif
#endif

179
src/crypto/bip39/pbkdf2.c Normal file
View File

@@ -0,0 +1,179 @@
/**
* Copyright (c) 2013-2014 Tomas Dzetkulic
* Copyright (c) 2013-2014 Pavol Rusnak
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "pbkdf2.h"
#include <string.h>
#include "hmac.h"
#include "memzero.h"
#include "sha2.h"
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass,
int passlen, const uint8_t *salt, int saltlen,
uint32_t blocknr) {
SHA256_CTX ctx = {0};
#if BYTE_ORDER == LITTLE_ENDIAN
REVERSE32(blocknr, blocknr);
#endif
hmac_sha256_prepare(pass, passlen, pctx->odig, pctx->idig);
memzero(pctx->g, sizeof(pctx->g));
pctx->g[8] = 0x80000000;
pctx->g[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
memcpy(ctx.state, pctx->idig, sizeof(pctx->idig));
ctx.bitcount = SHA256_BLOCK_LENGTH * 8;
sha256_Update(&ctx, salt, saltlen);
sha256_Update(&ctx, (uint8_t *)&blocknr, sizeof(blocknr));
sha256_Final(&ctx, (uint8_t *)pctx->g);
#if BYTE_ORDER == LITTLE_ENDIAN
for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) {
REVERSE32(pctx->g[k], pctx->g[k]);
}
#endif
sha256_Transform(pctx->odig, pctx->g, pctx->g);
memcpy(pctx->f, pctx->g, SHA256_DIGEST_LENGTH);
pctx->first = 1;
}
void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx,
uint32_t iterations) {
for (uint32_t i = pctx->first; i < iterations; i++) {
sha256_Transform(pctx->idig, pctx->g, pctx->g);
sha256_Transform(pctx->odig, pctx->g, pctx->g);
for (uint32_t j = 0; j < SHA256_DIGEST_LENGTH / sizeof(uint32_t); j++) {
pctx->f[j] ^= pctx->g[j];
}
}
pctx->first = 0;
}
void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key) {
#if BYTE_ORDER == LITTLE_ENDIAN
for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) {
REVERSE32(pctx->f[k], pctx->f[k]);
}
#endif
memcpy(key, pctx->f, SHA256_DIGEST_LENGTH);
memzero(pctx, sizeof(PBKDF2_HMAC_SHA256_CTX));
}
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt,
int saltlen, uint32_t iterations, uint8_t *key,
int keylen) {
uint32_t last_block_size = keylen % SHA256_DIGEST_LENGTH;
uint32_t blocks_count = keylen / SHA256_DIGEST_LENGTH;
if (last_block_size) {
blocks_count++;
} else {
last_block_size = SHA256_DIGEST_LENGTH;
}
for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) {
PBKDF2_HMAC_SHA256_CTX pctx = {0};
pbkdf2_hmac_sha256_Init(&pctx, pass, passlen, salt, saltlen, blocknr);
pbkdf2_hmac_sha256_Update(&pctx, iterations);
uint8_t digest[SHA256_DIGEST_LENGTH] = {0};
pbkdf2_hmac_sha256_Final(&pctx, digest);
uint32_t key_offset = (blocknr - 1) * SHA256_DIGEST_LENGTH;
if (blocknr < blocks_count) {
memcpy(key + key_offset, digest, SHA256_DIGEST_LENGTH);
} else {
memcpy(key + key_offset, digest, last_block_size);
}
}
}
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass,
int passlen, const uint8_t *salt, int saltlen,
uint32_t blocknr) {
SHA512_CTX ctx = {0};
#if BYTE_ORDER == LITTLE_ENDIAN
REVERSE32(blocknr, blocknr);
#endif
hmac_sha512_prepare(pass, passlen, pctx->odig, pctx->idig);
memzero(pctx->g, sizeof(pctx->g));
pctx->g[8] = 0x8000000000000000;
pctx->g[15] = (SHA512_BLOCK_LENGTH + SHA512_DIGEST_LENGTH) * 8;
memcpy(ctx.state, pctx->idig, sizeof(pctx->idig));
ctx.bitcount[0] = SHA512_BLOCK_LENGTH * 8;
ctx.bitcount[1] = 0;
sha512_Update(&ctx, salt, saltlen);
sha512_Update(&ctx, (uint8_t *)&blocknr, sizeof(blocknr));
sha512_Final(&ctx, (uint8_t *)pctx->g);
#if BYTE_ORDER == LITTLE_ENDIAN
for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) {
REVERSE64(pctx->g[k], pctx->g[k]);
}
#endif
sha512_Transform(pctx->odig, pctx->g, pctx->g);
memcpy(pctx->f, pctx->g, SHA512_DIGEST_LENGTH);
pctx->first = 1;
}
void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx,
uint32_t iterations) {
for (uint32_t i = pctx->first; i < iterations; i++) {
sha512_Transform(pctx->idig, pctx->g, pctx->g);
sha512_Transform(pctx->odig, pctx->g, pctx->g);
for (uint32_t j = 0; j < SHA512_DIGEST_LENGTH / sizeof(uint64_t); j++) {
pctx->f[j] ^= pctx->g[j];
}
}
pctx->first = 0;
}
void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key) {
#if BYTE_ORDER == LITTLE_ENDIAN
for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) {
REVERSE64(pctx->f[k], pctx->f[k]);
}
#endif
memcpy(key, pctx->f, SHA512_DIGEST_LENGTH);
memzero(pctx, sizeof(PBKDF2_HMAC_SHA512_CTX));
}
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt,
int saltlen, uint32_t iterations, uint8_t *key,
int keylen) {
uint32_t last_block_size = keylen % SHA512_DIGEST_LENGTH;
uint32_t blocks_count = keylen / SHA512_DIGEST_LENGTH;
if (last_block_size) {
blocks_count++;
} else {
last_block_size = SHA512_DIGEST_LENGTH;
}
for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) {
PBKDF2_HMAC_SHA512_CTX pctx = {0};
pbkdf2_hmac_sha512_Init(&pctx, pass, passlen, salt, saltlen, blocknr);
pbkdf2_hmac_sha512_Update(&pctx, iterations);
uint8_t digest[SHA512_DIGEST_LENGTH] = {0};
pbkdf2_hmac_sha512_Final(&pctx, digest);
uint32_t key_offset = (blocknr - 1) * SHA512_DIGEST_LENGTH;
if (blocknr < blocks_count) {
memcpy(key + key_offset, digest, SHA512_DIGEST_LENGTH);
} else {
memcpy(key + key_offset, digest, last_block_size);
}
}
}

66
src/crypto/bip39/pbkdf2.h Normal file
View File

@@ -0,0 +1,66 @@
/**
* Copyright (c) 2013-2014 Tomas Dzetkulic
* Copyright (c) 2013-2014 Pavol Rusnak
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __PBKDF2_H__
#define __PBKDF2_H__
#include <stdint.h>
#include "sha2.h"
typedef struct _PBKDF2_HMAC_SHA256_CTX {
uint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
uint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
uint32_t f[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
uint32_t g[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];
char first;
} PBKDF2_HMAC_SHA256_CTX;
typedef struct _PBKDF2_HMAC_SHA512_CTX {
uint64_t odig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
uint64_t idig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
uint64_t f[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
uint64_t g[SHA512_BLOCK_LENGTH / sizeof(uint64_t)];
char first;
} PBKDF2_HMAC_SHA512_CTX;
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass,
int passlen, const uint8_t *salt, int saltlen,
uint32_t blocknr);
void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx,
uint32_t iterations);
void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key);
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt,
int saltlen, uint32_t iterations, uint8_t *key,
int keylen);
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass,
int passlen, const uint8_t *salt, int saltlen,
uint32_t blocknr);
void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx,
uint32_t iterations);
void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key);
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt,
int saltlen, uint32_t iterations, uint8_t *key,
int keylen);
#endif

81
src/crypto/bip39/rand.c Normal file
View File

@@ -0,0 +1,81 @@
/**
* Copyright (c) 2013-2014 Tomas Dzetkulic
* Copyright (c) 2013-2014 Pavol Rusnak
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "rand.h"
#ifndef RAND_PLATFORM_INDEPENDENT
#pragma message( \
"NOT SUITABLE FOR PRODUCTION USE! Replace random32() function with your own secure code.")
// The following code is not supposed to be used in a production environment.
// It's included only to make the library testable.
// The message above tries to prevent any accidental use outside of the test
// environment.
//
// You are supposed to replace the random8() and random32() function with your
// own secure code. There is also a possibility to replace the random_buffer()
// function as it is defined as a weak symbol.
static uint32_t seed = 0;
void random_reseed(const uint32_t value) { seed = value; }
uint32_t random32(void) {
// Linear congruential generator from Numerical Recipes
// https://en.wikipedia.org/wiki/Linear_congruential_generator
seed = 1664525 * seed + 1013904223;
return seed;
}
#endif /* RAND_PLATFORM_INDEPENDENT */
//
// The following code is platform independent
//
void __attribute__((weak)) random_buffer(uint8_t *buf, size_t len) {
uint32_t r = 0;
for (size_t i = 0; i < len; i++) {
if (i % 4 == 0) {
r = random32();
}
buf[i] = (r >> ((i % 4) * 8)) & 0xFF;
}
}
uint32_t random_uniform(uint32_t n) {
uint32_t x = 0, max = 0xFFFFFFFF - (0xFFFFFFFF % n);
while ((x = random32()) >= max)
;
return x / (max / n);
}
void random_permute(char *str, size_t len) {
for (int i = len - 1; i >= 1; i--) {
int j = random_uniform(i + 1);
char t = str[j];
str[j] = str[i];
str[i] = t;
}
}

37
src/crypto/bip39/rand.h Normal file
View File

@@ -0,0 +1,37 @@
/**
* Copyright (c) 2013-2014 Tomas Dzetkulic
* Copyright (c) 2013-2014 Pavol Rusnak
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __RAND_H__
#define __RAND_H__
#include <stdint.h>
#include <stdlib.h>
void random_reseed(const uint32_t value);
uint32_t random32(void);
void random_buffer(uint8_t *buf, size_t len);
uint32_t random_uniform(uint32_t n);
void random_permute(char *buf, size_t len);
#endif

1283
src/crypto/bip39/sha2.c Normal file

File diff suppressed because it is too large Load Diff

116
src/crypto/bip39/sha2.h Normal file
View File

@@ -0,0 +1,116 @@
/**
* Copyright (c) 2000-2001 Aaron D. Gifford
* Copyright (c) 2013-2014 Pavol Rusnak
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __SHA2_H__
#define __SHA2_H__
#include <stdint.h>
#include <stddef.h>
#define SHA1_BLOCK_LENGTH 64
#define SHA1_DIGEST_LENGTH 20
#define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1)
#define SHA256_BLOCK_LENGTH 64
#define SHA256_DIGEST_LENGTH 32
#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
#define SHA512_BLOCK_LENGTH 128
#define SHA512_DIGEST_LENGTH 64
#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
typedef struct _SHA1_CTX {
uint32_t state[5];
uint64_t bitcount;
uint32_t buffer[SHA1_BLOCK_LENGTH/sizeof(uint32_t)];
} SHA1_CTX;
typedef struct _SHA256_CTX {
uint32_t state[8];
uint64_t bitcount;
uint32_t buffer[SHA256_BLOCK_LENGTH/sizeof(uint32_t)];
} SHA256_CTX;
typedef struct _SHA512_CTX {
uint64_t state[8];
uint64_t bitcount[2];
uint64_t buffer[SHA512_BLOCK_LENGTH/sizeof(uint64_t)];
} SHA512_CTX;
/*** ENDIAN REVERSAL MACROS *******************************************/
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#define BIG_ENDIAN 4321
#endif
#ifndef BYTE_ORDER
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
#define REVERSE32(w,x) { \
uint32_t tmp = (w); \
tmp = (tmp >> 16) | (tmp << 16); \
(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
}
#define REVERSE64(w,x) { \
uint64_t tmp = (w); \
tmp = (tmp >> 32) | (tmp << 32); \
tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
((tmp & 0x00ff00ff00ff00ffULL) << 8); \
(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
((tmp & 0x0000ffff0000ffffULL) << 16); \
}
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
extern const uint32_t sha256_initial_hash_value[8];
extern const uint64_t sha512_initial_hash_value[8];
void sha1_Transform(const uint32_t* state_in, const uint32_t* data, uint32_t* state_out);
void sha1_Init(SHA1_CTX *);
void sha1_Update(SHA1_CTX*, const uint8_t*, size_t);
void sha1_Final(SHA1_CTX*, uint8_t[SHA1_DIGEST_LENGTH]);
char* sha1_End(SHA1_CTX*, char[SHA1_DIGEST_STRING_LENGTH]);
void sha1_Raw(const uint8_t*, size_t, uint8_t[SHA1_DIGEST_LENGTH]);
char* sha1_Data(const uint8_t*, size_t, char[SHA1_DIGEST_STRING_LENGTH]);
void sha256_Transform(const uint32_t* state_in, const uint32_t* data, uint32_t* state_out);
void sha256_Init(SHA256_CTX *);
void sha256_Update(SHA256_CTX*, const uint8_t*, size_t);
void sha256_Final(SHA256_CTX*, uint8_t[SHA256_DIGEST_LENGTH]);
char* sha256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
void sha256_Raw(const uint8_t*, size_t, uint8_t[SHA256_DIGEST_LENGTH]);
char* sha256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
void sha512_Transform(const uint64_t* state_in, const uint64_t* data, uint64_t* state_out);
void sha512_Init(SHA512_CTX*);
void sha512_Update(SHA512_CTX*, const uint8_t*, size_t);
void sha512_Final(SHA512_CTX*, uint8_t[SHA512_DIGEST_LENGTH]);
char* sha512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
void sha512_Raw(const uint8_t*, size_t, uint8_t[SHA512_DIGEST_LENGTH]);
char* sha512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
#endif

397
src/crypto/bip39/sha3.c Normal file
View File

@@ -0,0 +1,397 @@
/* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak).
* based on the
* The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
* by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche
*
* Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so.
*
* 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. Use this program at your own risk!
*/
#include <assert.h>
#include <string.h>
#include "sha3.h"
#include "memzero.h"
#define I64(x) x##LL
#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
#define le2me_64(x) (x)
#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0)))
# define me64_to_le_str(to, from, length) memcpy((to), (from), (length))
/* constants */
#define NumberOfRounds 24
/* SHA3 (Keccak) constants for 24 rounds */
static uint64_t keccak_round_constants[NumberOfRounds] = {
I64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000),
I64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009),
I64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A),
I64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003),
I64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A),
I64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008)
};
/* Initializing a sha3 context for given number of output bits */
static void keccak_Init(SHA3_CTX *ctx, unsigned bits)
{
/* NB: The Keccak capacity parameter = bits * 2 */
unsigned rate = 1600 - bits * 2;
memzero(ctx, sizeof(SHA3_CTX));
ctx->block_size = rate / 8;
assert(rate <= 1600 && (rate % 64) == 0);
}
/**
* Initialize context before calculating hash.
*
* @param ctx context to initialize
*/
void sha3_224_Init(SHA3_CTX *ctx)
{
keccak_Init(ctx, 224);
}
/**
* Initialize context before calculating hash.
*
* @param ctx context to initialize
*/
void sha3_256_Init(SHA3_CTX *ctx)
{
keccak_Init(ctx, 256);
}
/**
* Initialize context before calculating hash.
*
* @param ctx context to initialize
*/
void sha3_384_Init(SHA3_CTX *ctx)
{
keccak_Init(ctx, 384);
}
/**
* Initialize context before calculating hash.
*
* @param ctx context to initialize
*/
void sha3_512_Init(SHA3_CTX *ctx)
{
keccak_Init(ctx, 512);
}
/* Keccak theta() transformation */
static void keccak_theta(uint64_t *A)
{
unsigned int x = 0;
uint64_t C[5] = {0}, D[5] = {0};
for (x = 0; x < 5; x++) {
C[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20];
}
D[0] = ROTL64(C[1], 1) ^ C[4];
D[1] = ROTL64(C[2], 1) ^ C[0];
D[2] = ROTL64(C[3], 1) ^ C[1];
D[3] = ROTL64(C[4], 1) ^ C[2];
D[4] = ROTL64(C[0], 1) ^ C[3];
for (x = 0; x < 5; x++) {
A[x] ^= D[x];
A[x + 5] ^= D[x];
A[x + 10] ^= D[x];
A[x + 15] ^= D[x];
A[x + 20] ^= D[x];
}
}
/* Keccak pi() transformation */
static void keccak_pi(uint64_t *A)
{
uint64_t A1 = 0;
A1 = A[1];
A[ 1] = A[ 6];
A[ 6] = A[ 9];
A[ 9] = A[22];
A[22] = A[14];
A[14] = A[20];
A[20] = A[ 2];
A[ 2] = A[12];
A[12] = A[13];
A[13] = A[19];
A[19] = A[23];
A[23] = A[15];
A[15] = A[ 4];
A[ 4] = A[24];
A[24] = A[21];
A[21] = A[ 8];
A[ 8] = A[16];
A[16] = A[ 5];
A[ 5] = A[ 3];
A[ 3] = A[18];
A[18] = A[17];
A[17] = A[11];
A[11] = A[ 7];
A[ 7] = A[10];
A[10] = A1;
/* note: A[ 0] is left as is */
}
/* Keccak chi() transformation */
static void keccak_chi(uint64_t *A)
{
int i = 0;
for (i = 0; i < 25; i += 5) {
uint64_t A0 = A[0 + i], A1 = A[1 + i];
A[0 + i] ^= ~A1 & A[2 + i];
A[1 + i] ^= ~A[2 + i] & A[3 + i];
A[2 + i] ^= ~A[3 + i] & A[4 + i];
A[3 + i] ^= ~A[4 + i] & A0;
A[4 + i] ^= ~A0 & A1;
}
}
static void sha3_permutation(uint64_t *state)
{
int round = 0;
for (round = 0; round < NumberOfRounds; round++)
{
keccak_theta(state);
/* apply Keccak rho() transformation */
state[ 1] = ROTL64(state[ 1], 1);
state[ 2] = ROTL64(state[ 2], 62);
state[ 3] = ROTL64(state[ 3], 28);
state[ 4] = ROTL64(state[ 4], 27);
state[ 5] = ROTL64(state[ 5], 36);
state[ 6] = ROTL64(state[ 6], 44);
state[ 7] = ROTL64(state[ 7], 6);
state[ 8] = ROTL64(state[ 8], 55);
state[ 9] = ROTL64(state[ 9], 20);
state[10] = ROTL64(state[10], 3);
state[11] = ROTL64(state[11], 10);
state[12] = ROTL64(state[12], 43);
state[13] = ROTL64(state[13], 25);
state[14] = ROTL64(state[14], 39);
state[15] = ROTL64(state[15], 41);
state[16] = ROTL64(state[16], 45);
state[17] = ROTL64(state[17], 15);
state[18] = ROTL64(state[18], 21);
state[19] = ROTL64(state[19], 8);
state[20] = ROTL64(state[20], 18);
state[21] = ROTL64(state[21], 2);
state[22] = ROTL64(state[22], 61);
state[23] = ROTL64(state[23], 56);
state[24] = ROTL64(state[24], 14);
keccak_pi(state);
keccak_chi(state);
/* apply iota(state, round) */
*state ^= keccak_round_constants[round];
}
}
/**
* The core transformation. Process the specified block of data.
*
* @param hash the algorithm state
* @param block the message block to process
* @param block_size the size of the processed block in bytes
*/
static void sha3_process_block(uint64_t hash[25], const uint64_t *block, size_t block_size)
{
/* expanded loop */
hash[ 0] ^= le2me_64(block[ 0]);
hash[ 1] ^= le2me_64(block[ 1]);
hash[ 2] ^= le2me_64(block[ 2]);
hash[ 3] ^= le2me_64(block[ 3]);
hash[ 4] ^= le2me_64(block[ 4]);
hash[ 5] ^= le2me_64(block[ 5]);
hash[ 6] ^= le2me_64(block[ 6]);
hash[ 7] ^= le2me_64(block[ 7]);
hash[ 8] ^= le2me_64(block[ 8]);
/* if not sha3-512 */
if (block_size > 72) {
hash[ 9] ^= le2me_64(block[ 9]);
hash[10] ^= le2me_64(block[10]);
hash[11] ^= le2me_64(block[11]);
hash[12] ^= le2me_64(block[12]);
/* if not sha3-384 */
if (block_size > 104) {
hash[13] ^= le2me_64(block[13]);
hash[14] ^= le2me_64(block[14]);
hash[15] ^= le2me_64(block[15]);
hash[16] ^= le2me_64(block[16]);
/* if not sha3-256 */
if (block_size > 136) {
hash[17] ^= le2me_64(block[17]);
#ifdef FULL_SHA3_FAMILY_SUPPORT
/* if not sha3-224 */
if (block_size > 144) {
hash[18] ^= le2me_64(block[18]);
hash[19] ^= le2me_64(block[19]);
hash[20] ^= le2me_64(block[20]);
hash[21] ^= le2me_64(block[21]);
hash[22] ^= le2me_64(block[22]);
hash[23] ^= le2me_64(block[23]);
hash[24] ^= le2me_64(block[24]);
}
#endif
}
}
}
/* make a permutation of the hash */
sha3_permutation(hash);
}
#define SHA3_FINALIZED 0x80000000
/**
* Calculate message hash.
* Can be called repeatedly with chunks of the message to be hashed.
*
* @param ctx the algorithm context containing current hashing state
* @param msg message chunk
* @param size length of the message chunk
*/
void sha3_Update(SHA3_CTX *ctx, const unsigned char *msg, size_t size)
{
size_t idx = (size_t)ctx->rest;
size_t block_size = (size_t)ctx->block_size;
if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */
ctx->rest = (unsigned)((ctx->rest + size) % block_size);
/* fill partial block */
if (idx) {
size_t left = block_size - idx;
memcpy((char*)ctx->message + idx, msg, (size < left ? size : left));
if (size < left) return;
/* process partial block */
sha3_process_block(ctx->hash, ctx->message, block_size);
msg += left;
size -= left;
}
while (size >= block_size) {
uint64_t *aligned_message_block = NULL;
if (IS_ALIGNED_64(msg)) {
/* the most common case is processing of an already aligned message
without copying it */
aligned_message_block = (uint64_t*)(void*)msg;
} else {
memcpy(ctx->message, msg, block_size);
aligned_message_block = ctx->message;
}
sha3_process_block(ctx->hash, aligned_message_block, block_size);
msg += block_size;
size -= block_size;
}
if (size) {
memcpy(ctx->message, msg, size); /* save leftovers */
}
}
/**
* Store calculated hash into the given array.
*
* @param ctx the algorithm context containing current hashing state
* @param result calculated hash in binary form
*/
void sha3_Final(SHA3_CTX *ctx, unsigned char* result)
{
size_t digest_length = 100 - ctx->block_size / 2;
const size_t block_size = ctx->block_size;
if (!(ctx->rest & SHA3_FINALIZED))
{
/* clear the rest of the data queue */
memzero((char*)ctx->message + ctx->rest, block_size - ctx->rest);
((char*)ctx->message)[ctx->rest] |= 0x06;
((char*)ctx->message)[block_size - 1] |= 0x80;
/* process final block */
sha3_process_block(ctx->hash, ctx->message, block_size);
ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
}
assert(block_size > digest_length);
if (result) me64_to_le_str(result, ctx->hash, digest_length);
memzero(ctx, sizeof(SHA3_CTX));
}
#if USE_KECCAK
/**
* Store calculated hash into the given array.
*
* @param ctx the algorithm context containing current hashing state
* @param result calculated hash in binary form
*/
void keccak_Final(SHA3_CTX *ctx, unsigned char* result)
{
size_t digest_length = 100 - ctx->block_size / 2;
const size_t block_size = ctx->block_size;
if (!(ctx->rest & SHA3_FINALIZED))
{
/* clear the rest of the data queue */
memzero((char*)ctx->message + ctx->rest, block_size - ctx->rest);
((char*)ctx->message)[ctx->rest] |= 0x01;
((char*)ctx->message)[block_size - 1] |= 0x80;
/* process final block */
sha3_process_block(ctx->hash, ctx->message, block_size);
ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
}
assert(block_size > digest_length);
if (result) me64_to_le_str(result, ctx->hash, digest_length);
memzero(ctx, sizeof(SHA3_CTX));
}
void keccak_256(const unsigned char* data, size_t len, unsigned char* digest)
{
SHA3_CTX ctx = {0};
keccak_256_Init(&ctx);
keccak_Update(&ctx, data, len);
keccak_Final(&ctx, digest);
}
void keccak_512(const unsigned char* data, size_t len, unsigned char* digest)
{
SHA3_CTX ctx = {0};
keccak_512_Init(&ctx);
keccak_Update(&ctx, data, len);
keccak_Final(&ctx, digest);
}
#endif /* USE_KECCAK */
void sha3_256(const unsigned char* data, size_t len, unsigned char* digest)
{
SHA3_CTX ctx = {0};
sha3_256_Init(&ctx);
sha3_Update(&ctx, data, len);
sha3_Final(&ctx, digest);
}
void sha3_512(const unsigned char* data, size_t len, unsigned char* digest)
{
SHA3_CTX ctx = {0};
sha3_512_Init(&ctx);
sha3_Update(&ctx, data, len);
sha3_Final(&ctx, digest);
}

89
src/crypto/bip39/sha3.h Normal file
View File

@@ -0,0 +1,89 @@
/* sha3.h - an implementation of Secure Hash Algorithm 3 (Keccak).
* based on the
* The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
* by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche
*
* Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so.
*
* 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. Use this program at your own risk!
*/
#ifndef __SHA3_H__
#define __SHA3_H__
#include <stdint.h>
#include "options.h"
#ifdef __cplusplus
extern "C" {
#endif
#define sha3_224_hash_size 28
#define sha3_256_hash_size 32
#define sha3_384_hash_size 48
#define sha3_512_hash_size 64
#define sha3_max_permutation_size 25
#define sha3_max_rate_in_qwords 24
#define SHA3_224_BLOCK_LENGTH 144
#define SHA3_256_BLOCK_LENGTH 136
#define SHA3_384_BLOCK_LENGTH 104
#define SHA3_512_BLOCK_LENGTH 72
#define SHA3_224_DIGEST_LENGTH sha3_224_hash_size
#define SHA3_256_DIGEST_LENGTH sha3_256_hash_size
#define SHA3_384_DIGEST_LENGTH sha3_384_hash_size
#define SHA3_512_DIGEST_LENGTH sha3_512_hash_size
/**
* SHA3 Algorithm context.
*/
typedef struct SHA3_CTX
{
/* 1600 bits algorithm hashing state */
uint64_t hash[sha3_max_permutation_size];
/* 1536-bit buffer for leftovers */
uint64_t message[sha3_max_rate_in_qwords];
/* count of bytes in the message[] buffer */
unsigned rest;
/* size of a message block processed at once */
unsigned block_size;
} SHA3_CTX;
/* methods for calculating the hash function */
void sha3_224_Init(SHA3_CTX *ctx);
void sha3_256_Init(SHA3_CTX *ctx);
void sha3_384_Init(SHA3_CTX *ctx);
void sha3_512_Init(SHA3_CTX *ctx);
void sha3_Update(SHA3_CTX *ctx, const unsigned char* msg, size_t size);
void sha3_Final(SHA3_CTX *ctx, unsigned char* result);
#if USE_KECCAK
#define keccak_224_Init sha3_224_Init
#define keccak_256_Init sha3_256_Init
#define keccak_384_Init sha3_384_Init
#define keccak_512_Init sha3_512_Init
#define keccak_Update sha3_Update
void keccak_Final(SHA3_CTX *ctx, unsigned char* result);
void keccak_256(const unsigned char* data, size_t len, unsigned char* digest);
void keccak_512(const unsigned char* data, size_t len, unsigned char* digest);
#endif
void sha3_256(const unsigned char* data, size_t len, unsigned char* digest);
void sha3_512(const unsigned char* data, size_t len, unsigned char* digest);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* __SHA3_H__ */

21
src/crypto/ctaes/COPYING Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Pieter Wuille
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,41 @@
ctaes
=====
Simple C module for constant-time AES encryption and decryption.
Features:
* Simple, pure C code without any dependencies.
* No tables or data-dependent branches whatsoever, but using bit sliced approach from https://eprint.iacr.org/2009/129.pdf.
* Very small object code: slightly over 4k of executable code when compiled with -Os.
* Slower than implementations based on precomputed tables or specialized instructions, but can do ~15 MB/s on modern CPUs.
Performance
-----------
Compiled with GCC 5.3.1 with -O3, on an Intel(R) Core(TM) i7-4800MQ CPU, numbers in CPU cycles:
| Algorithm | Key schedule | Encryption per byte | Decryption per byte |
| --------- | ------------:| -------------------:| -------------------:|
| AES-128 | 2.8k | 154 | 161 |
| AES-192 | 3.1k | 169 | 181 |
| AES-256 | 4.0k | 191 | 203 |
Build steps
-----------
Object code:
$ gcc -O3 ctaes.c -c -o ctaes.o
Tests:
$ gcc -O3 ctaes.c test.c -o test
Benchmark:
$ gcc -O3 ctaes.c bench.c -o bench
Review
------
Results of a formal review of the code can be found in http://bitcoin.sipa.be/ctaes/review.zip

170
src/crypto/ctaes/bench.c Normal file
View File

@@ -0,0 +1,170 @@
#include <stdio.h>
#include <math.h>
#include "sys/time.h"
#include "ctaes.h"
static double gettimedouble(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_usec * 0.000001 + tv.tv_sec;
}
static void print_number(double x) {
double y = x;
int c = 0;
if (y < 0.0) {
y = -y;
}
while (y < 100.0) {
y *= 10.0;
c++;
}
printf("%.*f", c, x);
}
static void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) {
int i;
double min = HUGE_VAL;
double sum = 0.0;
double max = 0.0;
for (i = 0; i < count; i++) {
double begin, total;
if (setup != NULL) {
setup(data);
}
begin = gettimedouble();
benchmark(data);
total = gettimedouble() - begin;
if (teardown != NULL) {
teardown(data);
}
if (total < min) {
min = total;
}
if (total > max) {
max = total;
}
sum += total;
}
printf("%s: min ", name);
print_number(min * 1000000000.0 / iter);
printf("ns / avg ");
print_number((sum / count) * 1000000000.0 / iter);
printf("ns / max ");
print_number(max * 1000000000.0 / iter);
printf("ns\n");
}
static void bench_AES128_init(void* data) {
AES128_ctx* ctx = (AES128_ctx*)data;
int i;
for (i = 0; i < 50000; i++) {
AES128_init(ctx, (unsigned char*)ctx);
}
}
static void bench_AES128_encrypt_setup(void* data) {
AES128_ctx* ctx = (AES128_ctx*)data;
static const unsigned char key[16] = {0};
AES128_init(ctx, key);
}
static void bench_AES128_encrypt(void* data) {
const AES128_ctx* ctx = (const AES128_ctx*)data;
unsigned char scratch[16] = {0};
int i;
for (i = 0; i < 4000000 / 16; i++) {
AES128_encrypt(ctx, 1, scratch, scratch);
}
}
static void bench_AES128_decrypt(void* data) {
const AES128_ctx* ctx = (const AES128_ctx*)data;
unsigned char scratch[16] = {0};
int i;
for (i = 0; i < 4000000 / 16; i++) {
AES128_decrypt(ctx, 1, scratch, scratch);
}
}
static void bench_AES192_init(void* data) {
AES192_ctx* ctx = (AES192_ctx*)data;
int i;
for (i = 0; i < 50000; i++) {
AES192_init(ctx, (unsigned char*)ctx);
}
}
static void bench_AES192_encrypt_setup(void* data) {
AES192_ctx* ctx = (AES192_ctx*)data;
static const unsigned char key[16] = {0};
AES192_init(ctx, key);
}
static void bench_AES192_encrypt(void* data) {
const AES192_ctx* ctx = (const AES192_ctx*)data;
unsigned char scratch[16] = {0};
int i;
for (i = 0; i < 4000000 / 16; i++) {
AES192_encrypt(ctx, 1, scratch, scratch);
}
}
static void bench_AES192_decrypt(void* data) {
const AES192_ctx* ctx = (const AES192_ctx*)data;
unsigned char scratch[16] = {0};
int i;
for (i = 0; i < 4000000 / 16; i++) {
AES192_decrypt(ctx, 1, scratch, scratch);
}
}
static void bench_AES256_init(void* data) {
AES256_ctx* ctx = (AES256_ctx*)data;
int i;
for (i = 0; i < 50000; i++) {
AES256_init(ctx, (unsigned char*)ctx);
}
}
static void bench_AES256_encrypt_setup(void* data) {
AES256_ctx* ctx = (AES256_ctx*)data;
static const unsigned char key[16] = {0};
AES256_init(ctx, key);
}
static void bench_AES256_encrypt(void* data) {
const AES256_ctx* ctx = (const AES256_ctx*)data;
unsigned char scratch[16] = {0};
int i;
for (i = 0; i < 4000000 / 16; i++) {
AES256_encrypt(ctx, 1, scratch, scratch);
}
}
static void bench_AES256_decrypt(void* data) {
const AES256_ctx* ctx = (const AES256_ctx*)data;
unsigned char scratch[16] = {0};
int i;
for (i = 0; i < 4000000 / 16; i++) {
AES256_decrypt(ctx, 1, scratch, scratch);
}
}
int main(void) {
AES128_ctx ctx128;
AES192_ctx ctx192;
AES256_ctx ctx256;
run_benchmark("aes128_init", bench_AES128_init, NULL, NULL, &ctx128, 20, 50000);
run_benchmark("aes128_encrypt_byte", bench_AES128_encrypt, bench_AES128_encrypt_setup, NULL, &ctx128, 20, 4000000);
run_benchmark("aes128_decrypt_byte", bench_AES128_decrypt, bench_AES128_encrypt_setup, NULL, &ctx128, 20, 4000000);
run_benchmark("aes192_init", bench_AES192_init, NULL, NULL, &ctx192, 20, 50000);
run_benchmark("aes192_encrypt_byte", bench_AES192_encrypt, bench_AES192_encrypt_setup, NULL, &ctx192, 20, 4000000);
run_benchmark("aes192_decrypt_byte", bench_AES192_decrypt, bench_AES192_encrypt_setup, NULL, &ctx192, 20, 4000000);
run_benchmark("aes256_init", bench_AES256_init, NULL, NULL, &ctx256, 20, 50000);
run_benchmark("aes256_encrypt_byte", bench_AES256_encrypt, bench_AES256_encrypt_setup, NULL, &ctx256, 20, 4000000);
run_benchmark("aes256_decrypt_byte", bench_AES256_decrypt, bench_AES256_encrypt_setup, NULL, &ctx256, 20, 4000000);
return 0;
}

556
src/crypto/ctaes/ctaes.c Normal file
View File

@@ -0,0 +1,556 @@
/*********************************************************************
* Copyright (c) 2016 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
/* Constant time, unoptimized, concise, plain C, AES implementation
* Based On:
* Emilia Kasper and Peter Schwabe, Faster and Timing-Attack Resistant AES-GCM
* http://www.iacr.org/archive/ches2009/57470001/57470001.pdf
* But using 8 16-bit integers representing a single AES state rather than 8 128-bit
* integers representing 8 AES states.
*/
#include "ctaes.h"
/* Slice variable slice_i contains the i'th bit of the 16 state variables in this order:
* 0 1 2 3
* 4 5 6 7
* 8 9 10 11
* 12 13 14 15
*/
/** Convert a byte to sliced form, storing it corresponding to given row and column in s */
static void LoadByte(AES_state* s, unsigned char byte, int r, int c) {
int i;
for (i = 0; i < 8; i++) {
s->slice[i] |= (byte & 1) << (r * 4 + c);
byte >>= 1;
}
}
/** Load 16 bytes of data into 8 sliced integers */
static void LoadBytes(AES_state *s, const unsigned char* data16) {
int c;
for (c = 0; c < 4; c++) {
int r;
for (r = 0; r < 4; r++) {
LoadByte(s, *(data16++), r, c);
}
}
}
/** Convert 8 sliced integers into 16 bytes of data */
static void SaveBytes(unsigned char* data16, const AES_state *s) {
int c;
for (c = 0; c < 4; c++) {
int r;
for (r = 0; r < 4; r++) {
int b;
uint8_t v = 0;
for (b = 0; b < 8; b++) {
v |= ((s->slice[b] >> (r * 4 + c)) & 1) << b;
}
*(data16++) = v;
}
}
}
/* S-box implementation based on the gate logic from:
* Joan Boyar and Rene Peralta, A depth-16 circuit for the AES S-box.
* https://eprint.iacr.org/2011/332.pdf
*/
static void SubBytes(AES_state *s, int inv) {
/* Load the bit slices */
uint16_t U0 = s->slice[7], U1 = s->slice[6], U2 = s->slice[5], U3 = s->slice[4];
uint16_t U4 = s->slice[3], U5 = s->slice[2], U6 = s->slice[1], U7 = s->slice[0];
uint16_t T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16;
uint16_t T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, D;
uint16_t M1, M6, M11, M13, M15, M20, M21, M22, M23, M25, M37, M38, M39, M40;
uint16_t M41, M42, M43, M44, M45, M46, M47, M48, M49, M50, M51, M52, M53, M54;
uint16_t M55, M56, M57, M58, M59, M60, M61, M62, M63;
if (inv) {
uint16_t R5, R13, R17, R18, R19;
/* Undo linear postprocessing */
T23 = U0 ^ U3;
T22 = ~(U1 ^ U3);
T2 = ~(U0 ^ U1);
T1 = U3 ^ U4;
T24 = ~(U4 ^ U7);
R5 = U6 ^ U7;
T8 = ~(U1 ^ T23);
T19 = T22 ^ R5;
T9 = ~(U7 ^ T1);
T10 = T2 ^ T24;
T13 = T2 ^ R5;
T3 = T1 ^ R5;
T25 = ~(U2 ^ T1);
R13 = U1 ^ U6;
T17 = ~(U2 ^ T19);
T20 = T24 ^ R13;
T4 = U4 ^ T8;
R17 = ~(U2 ^ U5);
R18 = ~(U5 ^ U6);
R19 = ~(U2 ^ U4);
D = U0 ^ R17;
T6 = T22 ^ R17;
T16 = R13 ^ R19;
T27 = T1 ^ R18;
T15 = T10 ^ T27;
T14 = T10 ^ R18;
T26 = T3 ^ T16;
} else {
/* Linear preprocessing. */
T1 = U0 ^ U3;
T2 = U0 ^ U5;
T3 = U0 ^ U6;
T4 = U3 ^ U5;
T5 = U4 ^ U6;
T6 = T1 ^ T5;
T7 = U1 ^ U2;
T8 = U7 ^ T6;
T9 = U7 ^ T7;
T10 = T6 ^ T7;
T11 = U1 ^ U5;
T12 = U2 ^ U5;
T13 = T3 ^ T4;
T14 = T6 ^ T11;
T15 = T5 ^ T11;
T16 = T5 ^ T12;
T17 = T9 ^ T16;
T18 = U3 ^ U7;
T19 = T7 ^ T18;
T20 = T1 ^ T19;
T21 = U6 ^ U7;
T22 = T7 ^ T21;
T23 = T2 ^ T22;
T24 = T2 ^ T10;
T25 = T20 ^ T17;
T26 = T3 ^ T16;
T27 = T1 ^ T12;
D = U7;
}
/* Non-linear transformation (shared between the forward and backward case) */
M1 = T13 & T6;
M6 = T3 & T16;
M11 = T1 & T15;
M13 = (T4 & T27) ^ M11;
M15 = (T2 & T10) ^ M11;
M20 = T14 ^ M1 ^ (T23 & T8) ^ M13;
M21 = (T19 & D) ^ M1 ^ T24 ^ M15;
M22 = T26 ^ M6 ^ (T22 & T9) ^ M13;
M23 = (T20 & T17) ^ M6 ^ M15 ^ T25;
M25 = M22 & M20;
M37 = M21 ^ ((M20 ^ M21) & (M23 ^ M25));
M38 = M20 ^ M25 ^ (M21 | (M20 & M23));
M39 = M23 ^ ((M22 ^ M23) & (M21 ^ M25));
M40 = M22 ^ M25 ^ (M23 | (M21 & M22));
M41 = M38 ^ M40;
M42 = M37 ^ M39;
M43 = M37 ^ M38;
M44 = M39 ^ M40;
M45 = M42 ^ M41;
M46 = M44 & T6;
M47 = M40 & T8;
M48 = M39 & D;
M49 = M43 & T16;
M50 = M38 & T9;
M51 = M37 & T17;
M52 = M42 & T15;
M53 = M45 & T27;
M54 = M41 & T10;
M55 = M44 & T13;
M56 = M40 & T23;
M57 = M39 & T19;
M58 = M43 & T3;
M59 = M38 & T22;
M60 = M37 & T20;
M61 = M42 & T1;
M62 = M45 & T4;
M63 = M41 & T2;
if (inv){
/* Undo linear preprocessing */
uint16_t P0 = M52 ^ M61;
uint16_t P1 = M58 ^ M59;
uint16_t P2 = M54 ^ M62;
uint16_t P3 = M47 ^ M50;
uint16_t P4 = M48 ^ M56;
uint16_t P5 = M46 ^ M51;
uint16_t P6 = M49 ^ M60;
uint16_t P7 = P0 ^ P1;
uint16_t P8 = M50 ^ M53;
uint16_t P9 = M55 ^ M63;
uint16_t P10 = M57 ^ P4;
uint16_t P11 = P0 ^ P3;
uint16_t P12 = M46 ^ M48;
uint16_t P13 = M49 ^ M51;
uint16_t P14 = M49 ^ M62;
uint16_t P15 = M54 ^ M59;
uint16_t P16 = M57 ^ M61;
uint16_t P17 = M58 ^ P2;
uint16_t P18 = M63 ^ P5;
uint16_t P19 = P2 ^ P3;
uint16_t P20 = P4 ^ P6;
uint16_t P22 = P2 ^ P7;
uint16_t P23 = P7 ^ P8;
uint16_t P24 = P5 ^ P7;
uint16_t P25 = P6 ^ P10;
uint16_t P26 = P9 ^ P11;
uint16_t P27 = P10 ^ P18;
uint16_t P28 = P11 ^ P25;
uint16_t P29 = P15 ^ P20;
s->slice[7] = P13 ^ P22;
s->slice[6] = P26 ^ P29;
s->slice[5] = P17 ^ P28;
s->slice[4] = P12 ^ P22;
s->slice[3] = P23 ^ P27;
s->slice[2] = P19 ^ P24;
s->slice[1] = P14 ^ P23;
s->slice[0] = P9 ^ P16;
} else {
/* Linear postprocessing */
uint16_t L0 = M61 ^ M62;
uint16_t L1 = M50 ^ M56;
uint16_t L2 = M46 ^ M48;
uint16_t L3 = M47 ^ M55;
uint16_t L4 = M54 ^ M58;
uint16_t L5 = M49 ^ M61;
uint16_t L6 = M62 ^ L5;
uint16_t L7 = M46 ^ L3;
uint16_t L8 = M51 ^ M59;
uint16_t L9 = M52 ^ M53;
uint16_t L10 = M53 ^ L4;
uint16_t L11 = M60 ^ L2;
uint16_t L12 = M48 ^ M51;
uint16_t L13 = M50 ^ L0;
uint16_t L14 = M52 ^ M61;
uint16_t L15 = M55 ^ L1;
uint16_t L16 = M56 ^ L0;
uint16_t L17 = M57 ^ L1;
uint16_t L18 = M58 ^ L8;
uint16_t L19 = M63 ^ L4;
uint16_t L20 = L0 ^ L1;
uint16_t L21 = L1 ^ L7;
uint16_t L22 = L3 ^ L12;
uint16_t L23 = L18 ^ L2;
uint16_t L24 = L15 ^ L9;
uint16_t L25 = L6 ^ L10;
uint16_t L26 = L7 ^ L9;
uint16_t L27 = L8 ^ L10;
uint16_t L28 = L11 ^ L14;
uint16_t L29 = L11 ^ L17;
s->slice[7] = L6 ^ L24;
s->slice[6] = ~(L16 ^ L26);
s->slice[5] = ~(L19 ^ L28);
s->slice[4] = L6 ^ L21;
s->slice[3] = L20 ^ L22;
s->slice[2] = L25 ^ L29;
s->slice[1] = ~(L13 ^ L27);
s->slice[0] = ~(L6 ^ L23);
}
}
#define BIT_RANGE(from,to) (((1 << ((to) - (from))) - 1) << (from))
#define BIT_RANGE_LEFT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) << (shift))
#define BIT_RANGE_RIGHT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) >> (shift))
static void ShiftRows(AES_state* s) {
int i;
for (i = 0; i < 8; i++) {
uint16_t v = s->slice[i];
s->slice[i] =
(v & BIT_RANGE(0, 4)) |
BIT_RANGE_LEFT(v, 4, 5, 3) | BIT_RANGE_RIGHT(v, 5, 8, 1) |
BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) |
BIT_RANGE_LEFT(v, 12, 15, 1) | BIT_RANGE_RIGHT(v, 15, 16, 3);
}
}
static void InvShiftRows(AES_state* s) {
int i;
for (i = 0; i < 8; i++) {
uint16_t v = s->slice[i];
s->slice[i] =
(v & BIT_RANGE(0, 4)) |
BIT_RANGE_LEFT(v, 4, 7, 1) | BIT_RANGE_RIGHT(v, 7, 8, 3) |
BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) |
BIT_RANGE_LEFT(v, 12, 13, 3) | BIT_RANGE_RIGHT(v, 13, 16, 1);
}
}
#define ROT(x,b) (((x) >> ((b) * 4)) | ((x) << ((4-(b)) * 4)))
static void MixColumns(AES_state* s, int inv) {
/* The MixColumns transform treats the bytes of the columns of the state as
* coefficients of a 3rd degree polynomial over GF(2^8) and multiplies them
* by the fixed polynomial a(x) = {03}x^3 + {01}x^2 + {01}x + {02}, modulo
* x^4 + {01}.
*
* In the inverse transform, we multiply by the inverse of a(x),
* a^-1(x) = {0b}x^3 + {0d}x^2 + {09}x + {0e}. This is equal to
* a(x) * ({04}x^2 + {05}), so we can reuse the forward transform's code
* (found in OpenSSL's bsaes-x86_64.pl, attributed to Jussi Kivilinna)
*
* In the bitsliced representation, a multiplication of every column by x
* mod x^4 + 1 is simply a right rotation.
*/
/* Shared for both directions is a multiplication by a(x), which can be
* rewritten as (x^3 + x^2 + x) + {02}*(x^3 + {01}).
*
* First compute s into the s? variables, (x^3 + {01}) * s into the s?_01
* variables and (x^3 + x^2 + x)*s into the s?_123 variables.
*/
uint16_t s0 = s->slice[0], s1 = s->slice[1], s2 = s->slice[2], s3 = s->slice[3];
uint16_t s4 = s->slice[4], s5 = s->slice[5], s6 = s->slice[6], s7 = s->slice[7];
uint16_t s0_01 = s0 ^ ROT(s0, 1), s0_123 = ROT(s0_01, 1) ^ ROT(s0, 3);
uint16_t s1_01 = s1 ^ ROT(s1, 1), s1_123 = ROT(s1_01, 1) ^ ROT(s1, 3);
uint16_t s2_01 = s2 ^ ROT(s2, 1), s2_123 = ROT(s2_01, 1) ^ ROT(s2, 3);
uint16_t s3_01 = s3 ^ ROT(s3, 1), s3_123 = ROT(s3_01, 1) ^ ROT(s3, 3);
uint16_t s4_01 = s4 ^ ROT(s4, 1), s4_123 = ROT(s4_01, 1) ^ ROT(s4, 3);
uint16_t s5_01 = s5 ^ ROT(s5, 1), s5_123 = ROT(s5_01, 1) ^ ROT(s5, 3);
uint16_t s6_01 = s6 ^ ROT(s6, 1), s6_123 = ROT(s6_01, 1) ^ ROT(s6, 3);
uint16_t s7_01 = s7 ^ ROT(s7, 1), s7_123 = ROT(s7_01, 1) ^ ROT(s7, 3);
/* Now compute s = s?_123 + {02} * s?_01. */
s->slice[0] = s7_01 ^ s0_123;
s->slice[1] = s7_01 ^ s0_01 ^ s1_123;
s->slice[2] = s1_01 ^ s2_123;
s->slice[3] = s7_01 ^ s2_01 ^ s3_123;
s->slice[4] = s7_01 ^ s3_01 ^ s4_123;
s->slice[5] = s4_01 ^ s5_123;
s->slice[6] = s5_01 ^ s6_123;
s->slice[7] = s6_01 ^ s7_123;
if (inv) {
/* In the reverse direction, we further need to multiply by
* {04}x^2 + {05}, which can be written as {04} * (x^2 + {01}) + {01}.
*
* First compute (x^2 + {01}) * s into the t?_02 variables: */
uint16_t t0_02 = s->slice[0] ^ ROT(s->slice[0], 2);
uint16_t t1_02 = s->slice[1] ^ ROT(s->slice[1], 2);
uint16_t t2_02 = s->slice[2] ^ ROT(s->slice[2], 2);
uint16_t t3_02 = s->slice[3] ^ ROT(s->slice[3], 2);
uint16_t t4_02 = s->slice[4] ^ ROT(s->slice[4], 2);
uint16_t t5_02 = s->slice[5] ^ ROT(s->slice[5], 2);
uint16_t t6_02 = s->slice[6] ^ ROT(s->slice[6], 2);
uint16_t t7_02 = s->slice[7] ^ ROT(s->slice[7], 2);
/* And then update s += {04} * t?_02 */
s->slice[0] ^= t6_02;
s->slice[1] ^= t6_02 ^ t7_02;
s->slice[2] ^= t0_02 ^ t7_02;
s->slice[3] ^= t1_02 ^ t6_02;
s->slice[4] ^= t2_02 ^ t6_02 ^ t7_02;
s->slice[5] ^= t3_02 ^ t7_02;
s->slice[6] ^= t4_02;
s->slice[7] ^= t5_02;
}
}
static void AddRoundKey(AES_state* s, const AES_state* round) {
int b;
for (b = 0; b < 8; b++) {
s->slice[b] ^= round->slice[b];
}
}
/** column_0(s) = column_c(a) */
static void GetOneColumn(AES_state* s, const AES_state* a, int c) {
int b;
for (b = 0; b < 8; b++) {
s->slice[b] = (a->slice[b] >> c) & 0x1111;
}
}
/** column_c1(r) |= (column_0(s) ^= column_c2(a)) */
static void KeySetupColumnMix(AES_state* s, AES_state* r, const AES_state* a, int c1, int c2) {
int b;
for (b = 0; b < 8; b++) {
r->slice[b] |= ((s->slice[b] ^= ((a->slice[b] >> c2) & 0x1111)) & 0x1111) << c1;
}
}
/** Rotate the rows in s one position upwards, and xor in r */
static void KeySetupTransform(AES_state* s, const AES_state* r) {
int b;
for (b = 0; b < 8; b++) {
s->slice[b] = ((s->slice[b] >> 4) | (s->slice[b] << 12)) ^ r->slice[b];
}
}
/* Multiply the cells in s by x, as polynomials over GF(2) mod x^8 + x^4 + x^3 + x + 1 */
static void MultX(AES_state* s) {
uint16_t top = s->slice[7];
s->slice[7] = s->slice[6];
s->slice[6] = s->slice[5];
s->slice[5] = s->slice[4];
s->slice[4] = s->slice[3] ^ top;
s->slice[3] = s->slice[2] ^ top;
s->slice[2] = s->slice[1];
s->slice[1] = s->slice[0] ^ top;
s->slice[0] = top;
}
/** Expand the cipher key into the key schedule.
*
* state must be a pointer to an array of size nrounds + 1.
* key must be a pointer to 4 * nkeywords bytes.
*
* AES128 uses nkeywords = 4, nrounds = 10
* AES192 uses nkeywords = 6, nrounds = 12
* AES256 uses nkeywords = 8, nrounds = 14
*/
static void AES_setup(AES_state* rounds, const uint8_t* key, int nkeywords, int nrounds)
{
int i;
/* The one-byte round constant */
AES_state rcon = {{1,0,0,0,0,0,0,0}};
/* The number of the word being generated, modulo nkeywords */
int pos = 0;
/* The column representing the word currently being processed */
AES_state column;
for (i = 0; i < nrounds + 1; i++) {
int b;
for (b = 0; b < 8; b++) {
rounds[i].slice[b] = 0;
}
}
/* The first nkeywords round columns are just taken from the key directly. */
for (i = 0; i < nkeywords; i++) {
int r;
for (r = 0; r < 4; r++) {
LoadByte(&rounds[i >> 2], *(key++), r, i & 3);
}
}
GetOneColumn(&column, &rounds[(nkeywords - 1) >> 2], (nkeywords - 1) & 3);
for (i = nkeywords; i < 4 * (nrounds + 1); i++) {
/* Transform column */
if (pos == 0) {
SubBytes(&column, 0);
KeySetupTransform(&column, &rcon);
MultX(&rcon);
} else if (nkeywords > 6 && pos == 4) {
SubBytes(&column, 0);
}
if (++pos == nkeywords) pos = 0;
KeySetupColumnMix(&column, &rounds[i >> 2], &rounds[(i - nkeywords) >> 2], i & 3, (i - nkeywords) & 3);
}
}
static void AES_encrypt(const AES_state* rounds, int nrounds, unsigned char* cipher16, const unsigned char* plain16) {
AES_state s = {{0}};
int round;
LoadBytes(&s, plain16);
AddRoundKey(&s, rounds++);
for (round = 1; round < nrounds; round++) {
SubBytes(&s, 0);
ShiftRows(&s);
MixColumns(&s, 0);
AddRoundKey(&s, rounds++);
}
SubBytes(&s, 0);
ShiftRows(&s);
AddRoundKey(&s, rounds);
SaveBytes(cipher16, &s);
}
static void AES_decrypt(const AES_state* rounds, int nrounds, unsigned char* plain16, const unsigned char* cipher16) {
/* Most AES decryption implementations use the alternate scheme
* (the Equivalent Inverse Cipher), which allows for more code reuse between
* the encryption and decryption code, but requires separate setup for both.
*/
AES_state s = {{0}};
int round;
rounds += nrounds;
LoadBytes(&s, cipher16);
AddRoundKey(&s, rounds--);
for (round = 1; round < nrounds; round++) {
InvShiftRows(&s);
SubBytes(&s, 1);
AddRoundKey(&s, rounds--);
MixColumns(&s, 1);
}
InvShiftRows(&s);
SubBytes(&s, 1);
AddRoundKey(&s, rounds);
SaveBytes(plain16, &s);
}
void AES128_init(AES128_ctx* ctx, const unsigned char* key16) {
AES_setup(ctx->rk, key16, 4, 10);
}
void AES128_encrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) {
while (blocks--) {
AES_encrypt(ctx->rk, 10, cipher16, plain16);
cipher16 += 16;
plain16 += 16;
}
}
void AES128_decrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) {
while (blocks--) {
AES_decrypt(ctx->rk, 10, plain16, cipher16);
cipher16 += 16;
plain16 += 16;
}
}
void AES192_init(AES192_ctx* ctx, const unsigned char* key24) {
AES_setup(ctx->rk, key24, 6, 12);
}
void AES192_encrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) {
while (blocks--) {
AES_encrypt(ctx->rk, 12, cipher16, plain16);
cipher16 += 16;
plain16 += 16;
}
}
void AES192_decrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) {
while (blocks--) {
AES_decrypt(ctx->rk, 12, plain16, cipher16);
cipher16 += 16;
plain16 += 16;
}
}
void AES256_init(AES256_ctx* ctx, const unsigned char* key32) {
AES_setup(ctx->rk, key32, 8, 14);
}
void AES256_encrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) {
while (blocks--) {
AES_encrypt(ctx->rk, 14, cipher16, plain16);
cipher16 += 16;
plain16 += 16;
}
}
void AES256_decrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) {
while (blocks--) {
AES_decrypt(ctx->rk, 14, plain16, cipher16);
cipher16 += 16;
plain16 += 16;
}
}

41
src/crypto/ctaes/ctaes.h Normal file
View File

@@ -0,0 +1,41 @@
/*********************************************************************
* Copyright (c) 2016 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _CTAES_H_
#define _CTAES_H_ 1
#include <stdint.h>
#include <stdlib.h>
typedef struct {
uint16_t slice[8];
} AES_state;
typedef struct {
AES_state rk[11];
} AES128_ctx;
typedef struct {
AES_state rk[13];
} AES192_ctx;
typedef struct {
AES_state rk[15];
} AES256_ctx;
void AES128_init(AES128_ctx* ctx, const unsigned char* key16);
void AES128_encrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16);
void AES128_decrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16);
void AES192_init(AES192_ctx* ctx, const unsigned char* key24);
void AES192_encrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16);
void AES192_decrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16);
void AES256_init(AES256_ctx* ctx, const unsigned char* key32);
void AES256_encrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16);
void AES256_decrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16);
#endif

110
src/crypto/ctaes/test.c Normal file
View File

@@ -0,0 +1,110 @@
/*********************************************************************
* Copyright (c) 2016 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#include "ctaes.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef struct {
int keysize;
const char* key;
const char* plain;
const char* cipher;
} ctaes_test;
static const ctaes_test ctaes_tests[] = {
/* AES test vectors from FIPS 197. */
{128, "000102030405060708090a0b0c0d0e0f", "00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a"},
{192, "000102030405060708090a0b0c0d0e0f1011121314151617", "00112233445566778899aabbccddeeff", "dda97ca4864cdfe06eaf70a0ec0d7191"},
{256, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089"},
/* AES-ECB test vectors from NIST sp800-38a. */
{128, "2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97"},
{128, "2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf"},
{128, "2b7e151628aed2a6abf7158809cf4f3c", "30c81c46a35ce411e5fbc1191a0a52ef", "43b1cd7f598ece23881b00e3ed030688"},
{128, "2b7e151628aed2a6abf7158809cf4f3c", "f69f2445df4f9b17ad2b417be66c3710", "7b0c785e27e8ad3f8223207104725dd4"},
{192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "6bc1bee22e409f96e93d7e117393172a", "bd334f1d6e45f25ff712a214571fa5cc"},
{192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "ae2d8a571e03ac9c9eb76fac45af8e51", "974104846d0ad3ad7734ecb3ecee4eef"},
{192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "30c81c46a35ce411e5fbc1191a0a52ef", "ef7afd2270e2e60adce0ba2face6444e"},
{192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "f69f2445df4f9b17ad2b417be66c3710", "9a4b41ba738d6c72fb16691603c18e0e"},
{256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8"},
{256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870"},
{256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d"},
{256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7"}
};
static void from_hex(unsigned char* data, int len, const char* hex) {
int p;
for (p = 0; p < len; p++) {
int v = 0;
int n;
for (n = 0; n < 2; n++) {
assert((*hex >= '0' && *hex <= '9') || (*hex >= 'a' && *hex <= 'f'));
if (*hex >= '0' && *hex <= '9') {
v |= (*hex - '0') << (4 * (1 - n));
} else {
v |= (*hex - 'a' + 10) << (4 * (1 - n));
}
hex++;
}
*(data++) = v;
}
assert(*hex == 0);
}
int main(void) {
int i;
int fail = 0;
for (i = 0; i < sizeof(ctaes_tests) / sizeof(ctaes_tests[0]); i++) {
unsigned char key[32], plain[16], cipher[16], ciphered[16], deciphered[16];
const ctaes_test* test = &ctaes_tests[i];
assert(test->keysize == 128 || test->keysize == 192 || test->keysize == 256);
from_hex(plain, 16, test->plain);
from_hex(cipher, 16, test->cipher);
switch (test->keysize) {
case 128: {
AES128_ctx ctx;
from_hex(key, 16, test->key);
AES128_init(&ctx, key);
AES128_encrypt(&ctx, 1, ciphered, plain);
AES128_decrypt(&ctx, 1, deciphered, cipher);
break;
}
case 192: {
AES192_ctx ctx;
from_hex(key, 24, test->key);
AES192_init(&ctx, key);
AES192_encrypt(&ctx, 1, ciphered, plain);
AES192_decrypt(&ctx, 1, deciphered, cipher);
break;
}
case 256: {
AES256_ctx ctx;
from_hex(key, 32, test->key);
AES256_init(&ctx, key);
AES256_encrypt(&ctx, 1, ciphered, plain);
AES256_decrypt(&ctx, 1, deciphered, cipher);
break;
}
}
if (memcmp(cipher, ciphered, 16)) {
fprintf(stderr, "E(key=\"%s\", plain=\"%s\") != \"%s\"\n", test->key, test->plain, test->cipher);
fail++;
}
if (memcmp(plain, deciphered, 16)) {
fprintf(stderr, "D(key=\"%s\", cipher=\"%s\") != \"%s\"\n", test->key, test->cipher, test->plain);
fail++;
}
}
if (fail == 0) {
fprintf(stderr, "All tests successful\n");
} else {
fprintf(stderr, "%i tests failed\n", fail);
}
return (fail != 0);
}

View File

@@ -1,5 +1,5 @@
#!/bin/bash
# Copyright (c) 2019 Hush developers
# Copyright (c) 2019-2020 Hush developers
# set working directory to the location of this script
# readlink -f does not always exist
@@ -8,31 +8,41 @@ cd $DIR
DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )"
cd $DIR
# Chain parameters
NAME=HUSH3
# this corresponds to FR address RHushEyeDm7XwtaTWtyCbjGQumYyV8vMjn
SCRIPT=76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac
# Chain parameters
# First Pure Sapling Zcash Protocol chain!
SAPLING=1
# We use 3 "eras" of different supply curves
ERAS=3
BLOCKTIME=150
# 6250000 - (sprout pool at block 500,000)
# These values are historical and over-ridden by internals!
# Do not change these values, change internals.
BLOCKTIME=150 # Hush goes to 75s blocktime at Block 340K
REWARD=0,1125000000,562500000
HALVING=129,340000,840000
PERC=11111111
END=128,340000,5422111
# 6250000 - (Sprout pool at block 500,000)
SUPPLY=6178674
FOUNDERS=1
REWARD=0,1125000000,562500000
PERC=11111111
HALVING=129,340000,840000
# NOTE: keep in sync with komodo_bitcoind.h
END=128,340000,5422111
CLIENTNAME=GoldenSandtrout
NODE1=188.165.212.101 # EU
NODE2=64.120.113.130 # AR
NODE3=209.58.144.205 # NA
NODE4=94.130.35.94 # EU
CCLIB=hush3
# First Pure Sapling Zcash Protocol chain!
SAPLING=1
# CryptoConditions/Custom Consensus params
# CCs will effectively be turned off at Block 340K
# since transparent outputs will not be allowed, except
# for mining and dpow. CCs can be used on Hush Smart
# Chains that do not define ac_private=1
FAUCET=228
HEIR=234
CHANNEL=235
@@ -53,7 +63,6 @@ else
fi
fi
$KMD -ac_name=$NAME \
-ac_sapling=$SAPLING \
-ac_reward=$REWARD \

View File

@@ -1,5 +1,5 @@
#!/bin/bash
# Copyright (c) 2019 Hush developers
# Copyright (c) 2019-2020 Hush developers
# set working directory to the location of this script
DIR="$( cd "$( dirname "$( readlink -f "${BASH_SOURCE[0]}" )" )" && pwd )"

View File

@@ -454,7 +454,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-maxtxfee=<amt>", strprintf(_("Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)"),
CURRENCY_UNIT, FormatMoney(maxTxFee)));
strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format") + " " + _("on startup"));
strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), "wallet.dat"));
strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file absolute path or a path relative to the data directory") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT));
strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), true));
strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
strUsage += HelpMessageOpt("-whitelistaddress=<Raddress>", _("Enable the wallet filter for notary nodes and add one Raddress to the whitelist of the wallet filter. If -whitelistaddress= is used, then the wallet filter is automatically activated. Several Raddresses can be defined using several -whitelistaddress= (similar to -addnode). The wallet filter will filter the utxo to only ones coming from my own Raddress (derived from pubkey) and each Raddress defined using -whitelistaddress= this option is mostly for Notary Nodes)."));

View File

@@ -1234,52 +1234,83 @@ int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);
// This function defines the Hush Founders Reward (AKA Dev Tax)
// 10% of all block rewards go towards Hush core team
// If you do not like this, you are encouraged to fork the chain
// or start your own Hush Smart Chain: https://github.com/myhush/hush-smart-chains
uint64_t komodo_commission(const CBlock *pblock,int32_t height)
{
static bool didinit = false,ishush3 = false;
// LABS fungible chains, cannot have any block reward!
if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 )
return(0);
fprintf(stderr,"%s at height=%d\n",__func__,height);
static bool didinit = false, ishush3 = false;
if (!didinit) {
ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false;
didinit = true;
fprintf(stderr,"%s: didinit ishush3=%d\n", __func__, ishush3);
}
int32_t i,j,n=0,txn_count; int64_t nSubsidy; uint64_t commission,total = 0;
if ( ASSETCHAINS_FOUNDERS != 0 )
{
nSubsidy = GetBlockSubsidy(height,Params().GetConsensus());
//fprintf(stderr,"ht.%d nSubsidy %.8f prod %llu\n",height,(double)nSubsidy/COIN,(long long)(nSubsidy * ASSETCHAINS_COMMISSION));
fprintf(stderr,"ht.%d nSubsidy %.8f prod %llu\n",height,(double)nSubsidy/COIN,(long long)(nSubsidy * ASSETCHAINS_COMMISSION));
commission = ((nSubsidy * ASSETCHAINS_COMMISSION) / COIN);
// Do not change this code unless you really know what you are doing.
// Here Be Dragons! -- Duke Leto
if (ishush3) {
int32_t starting_commission = 125000000, HALVING1 = 340000, INTERVAL = 840000, TRANSITION = 129, BR_END = 5422111;
// TODO: Calculate new BR_END based on 75s block time!!! 2X old BR_END is a rough estimate, not exact!
int32_t starting_commission = 125000000, HALVING1 = GetArg("-z2zheight",340000),
INTERVAL = GetArg("-ac_halving1",840000), TRANSITION = 129, BR_END = 2*5422111;
// TODO: how many halvings will we have given new 75s blocktime?
int32_t commisions[] = {starting_commission, 31250000, 15625000, 78125000, 39062500, 19531250, 9765625, // these are exact
4882812, 2441406, 1220703, 610351 // these have deviation from ideal BR
// Just like BTC, BRs in the far future will be slightly less than
// they should be because exact values are not integers, causing
// slightly less coins to be actually mined
};
// HUSH supply curve cannot be exactly represented via KMD AC CLI args, so we do it ourselves.
// You specify the BR, and the FR % gets added so 10% of 12.5 is 1.25
// but to tell the AC params, I need to say "11% of 11.25" is 1.25
// 11% ie. 1/9th cannot be exactly represented and so the FR has tiny amounts of error unless done manually
if( height > HALVING1) {
// Block time going from 150s to 75s (half) means the interval between halvings
// must be twice as often, i.e. 840000*2=1680000
// With 150s blocks, we have 210,000 blocks per year
// With 75s blocks, we have 420,000 blocks per year
INTERVAL = GetArg("-ac_halving2",1680000);
}
// Transition period of 128 blocks has BR=FR=0
if (height < TRANSITION) {
commission = 0;
} else if (height < HALVING1) {
commission = starting_commission;
} else if (height < HALVING1+1*INTERVAL) {
commission = starting_commission / 2;
} else if (height < HALVING1+2*INTERVAL) {
commission = starting_commission / 4;
} else if (height < HALVING1+3*INTERVAL) {
commission = starting_commission / 8;
} else if (height < HALVING1+4*INTERVAL) {
commission = starting_commission / 16;
} else if (height < HALVING1+5*INTERVAL) {
commission = starting_commission / 32;
} else if (height < HALVING1+6*INTERVAL) { // Block 5380000
// Block reward will go to zero between 7th+8th halvings, ac_end may need adjusting
commission = starting_commission / 64;
} else if (height < HALVING1+7*INTERVAL) {
// Block reward will be zero before this is ever reached
commission = starting_commission / 128; // Block 6220000
} else if (height < HALVING1) { // before 1st Halving @ Block 340000 (Nov 2020)
commission = commisions[0];
} else if (height < HALVING1+1*INTERVAL) { // before 2nd Halving @ Block 2020000
commission = commisions[1];
} else if (height < HALVING1+2*INTERVAL) { // before 3rd Halving @ Block 3700000
commission = commisions[2];
} else if (height < HALVING1+3*INTERVAL) { // before 4th Halving @ Block 5380000
commission = commisions[3];
} else if (height < HALVING1+4*INTERVAL) { // before 5th Halving @ Block 7060000
commission = commisions[4];
} else if (height < HALVING1+5*INTERVAL) { // before 6th Halving @ Block 8740000
commission = commisions[5];
} else if (height < HALVING1+6*INTERVAL) { // before 7th Halving @ Block 10420000
commission = commisions[6];
} else if (height < HALVING1+7*INTERVAL) { // before 8th Halving @ Block 12100000
// TODO: Still true??? Block reward will go to zero between 7th+8th halvings, ac_end may need adjusting
commission = commisions[7];
} else if (height < HALVING1+8*INTERVAL) { // before 9th Halving @ Block 13780000
// BR should be zero before this halving happens
commission = commisions[8];
}
// Explicitly set the last block reward
// BR_END is the block with the last non-zero block reward, which overrides
// the -ac_end param on HUSH3
if(height > BR_END) {
commission = 0;
}
}
@@ -1968,20 +1999,21 @@ void GetKomodoEarlytxidScriptPub()
int64_t komodo_checkcommission(CBlock *pblock,int32_t height)
{
fprintf(stderr,"%s at height=%d\n",__func__,height);
int64_t checktoshis=0; uint8_t *script,scripthex[8192]; int32_t scriptlen,matched = 0; static bool didinit = false;
if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 )
{
checktoshis = komodo_commission(pblock,height);
if ( checktoshis >= 10000 && pblock->vtx[0].vout.size() < 2 )
{
//fprintf(stderr,"komodo_checkcommission vsize.%d height.%d commission %.8f\n",(int32_t)pblock->vtx[0].vout.size(),height,(double)checktoshis/COIN);
fprintf(stderr,"komodo_checkcommission vsize.%d height.%d commission %.8f\n",(int32_t)pblock->vtx[0].vout.size(),height,(double)checktoshis/COIN);
return(-1);
}
else if ( checktoshis != 0 )
{
script = (uint8_t *)&pblock->vtx[0].vout[1].scriptPubKey[0];
scriptlen = (int32_t)pblock->vtx[0].vout[1].scriptPubKey.size();
if ( 0 )
if ( 1 )
{
int32_t i;
for (i=0; i<scriptlen; i++)

View File

@@ -1534,24 +1534,44 @@ char *argv0names[] =
(char *)"MNZ", (char *)"MNZ", (char *)"MNZ", (char *)"MNZ", (char *)"BTCH", (char *)"BTCH", (char *)"BTCH", (char *)"BTCH"
};
// Large total supplies lead to numerical errors, beware!
uint64_t komodo_max_money()
{
return komodo_current_supply(10000000);
}
uint64_t hush_block_subsidy(int nHeight)
{
uint64_t subsidy=0;
//TODO: Cover all halvings until BR=0
//if (nHeight >= 3700000) {
// subsidy = ASSETCHAINS_REWARD[4];
//} else
if (nHeight >= 2020000) {
subsidy = 140625000;
} else if (nHeight >= GetArg("-z2zheight",340000)) {
subsidy = 281250000;
} else if (nHeight >= 128) {
subsidy = 1125000000;
}
return subsidy;
}
uint64_t komodo_ac_block_subsidy(int nHeight)
{
// we have to find our era, start from beginning reward, and determine current subsidy
fprintf(stderr,"%s: ht.%d\n", __func__, nHeight);
// Find current era, start from beginning reward, and determine current subsidy
int64_t numerator, denominator, subsidy = 0;
int64_t subsidyDifference;
int32_t numhalvings, curEra = 0, sign = 1;
static uint64_t cached_subsidy; static int32_t cached_numhalvings; static int cached_era;
bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false;
// check for backwards compat, older chains with no explicit rewards had 0.0001 block reward
if ( ASSETCHAINS_ENDSUBSIDY[0] == 0 && ASSETCHAINS_REWARD[0] == 0 )
if ( ASSETCHAINS_ENDSUBSIDY[0] == 0 && ASSETCHAINS_REWARD[0] == 0 ) {
fprintf(stderr,"%s: defaulting to 0.0001 subsidy\n",__func__);
subsidy = 10000;
else if ( (ASSETCHAINS_ENDSUBSIDY[0] == 0 && ASSETCHAINS_REWARD[0] != 0) || ASSETCHAINS_ENDSUBSIDY[0] != 0 )
{
} else if ( (ASSETCHAINS_ENDSUBSIDY[0] == 0 && ASSETCHAINS_REWARD[0] != 0) || ASSETCHAINS_ENDSUBSIDY[0] != 0 ) {
// if we have an end block in the first era, find our current era
if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 )
{
@@ -1561,26 +1581,30 @@ uint64_t komodo_ac_block_subsidy(int nHeight)
break;
}
}
if ( curEra <= ASSETCHAINS_LASTERA )
{
int64_t nStart = curEra ? ASSETCHAINS_ENDSUBSIDY[curEra - 1] : 0;
subsidy = (int64_t)ASSETCHAINS_REWARD[curEra];
fprintf(stderr,"%s: nStart.%ld subsidy.%ld curEra.%d\n",__func__,nStart,subsidy,curEra);
if ( subsidy || (curEra != ASSETCHAINS_LASTERA && ASSETCHAINS_REWARD[curEra + 1] != 0) )
{
if ( ASSETCHAINS_HALVING[curEra] != 0 )
{
if ( (numhalvings = ((nHeight - nStart) / ASSETCHAINS_HALVING[curEra])) > 0 )
{
if ( ASSETCHAINS_DECAY[curEra] == 0 )
if (ishush3) {
subsidy = hush_block_subsidy(nHeight);
fprintf(stderr,"%s: HUSH3 subsidy=%ld at height=%d\n",__func__,subsidy,nHeight);
} else if ( (numhalvings = ((nHeight - nStart) / ASSETCHAINS_HALVING[curEra])) > 0 ) {
// The code below is not compatible with HUSH3 mainnet
if ( ASSETCHAINS_DECAY[curEra] == 0 ) {
subsidy >>= numhalvings;
else if ( ASSETCHAINS_DECAY[curEra] == 100000000 && ASSETCHAINS_ENDSUBSIDY[curEra] != 0 )
{
fprintf(stderr,"%s: no decay, numhalvings.%d curEra.%d subsidy.%ld nStart.%ld\n",__func__, numhalvings, curEra, subsidy, nStart);
} else if ( ASSETCHAINS_DECAY[curEra] == 100000000 && ASSETCHAINS_ENDSUBSIDY[curEra] != 0 ) {
if ( curEra == ASSETCHAINS_LASTERA )
{
subsidyDifference = subsidy;
}
else
{
} else {
// Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0
subsidyDifference = subsidy - ASSETCHAINS_REWARD[curEra + 1];
if (subsidyDifference < 0)
@@ -1592,13 +1616,10 @@ uint64_t komodo_ac_block_subsidy(int nHeight)
denominator = ASSETCHAINS_ENDSUBSIDY[curEra] - nStart;
numerator = denominator - ((ASSETCHAINS_ENDSUBSIDY[curEra] - nHeight) + ((nHeight - nStart) % ASSETCHAINS_HALVING[curEra]));
subsidy = subsidy - sign * ((subsidyDifference * numerator) / denominator);
}
else
{
if ( cached_subsidy > 0 && cached_era == curEra && cached_numhalvings == numhalvings )
} else {
if ( cached_subsidy > 0 && cached_era == curEra && cached_numhalvings == numhalvings ) {
subsidy = cached_subsidy;
else
{
} else {
for (int i=0; i < numhalvings && subsidy != 0; i++)
subsidy = (subsidy * ASSETCHAINS_DECAY[curEra]) / 100000000;
cached_subsidy = subsidy;
@@ -1609,28 +1630,27 @@ uint64_t komodo_ac_block_subsidy(int nHeight)
}
}
}
} else {
fprintf(stderr,"%s: curEra.%d > lastEra.%lu\n", __func__, curEra, ASSETCHAINS_LASTERA);
}
}
uint32_t magicExtra = ASSETCHAINS_STAKED ? ASSETCHAINS_MAGIC : (ASSETCHAINS_MAGIC & 0xffffff);
if ( ASSETCHAINS_SUPPLY > 10000000000 ) // over 10 billion?
{
fprintf(stderr,"%s: Detected supply over 10 billion, danger zone!\n",__func__);
if ( nHeight <= ASSETCHAINS_SUPPLY/1000000000 )
{
subsidy += (uint64_t)1000000000 * COIN;
if ( nHeight == 1 )
subsidy += (ASSETCHAINS_SUPPLY % 1000000000)*COIN + magicExtra;
}
}
else if ( nHeight == 1 )
{
} else if ( nHeight == 1 ) {
if ( ASSETCHAINS_LASTERA == 0 )
subsidy = ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra;
else
subsidy += ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra;
}
else if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 )
return(0);
// LABS fungible chains, cannot have any block reward!
fprintf(stderr,"%s: ht.%d curEra.%d lastEra.%lu subsidy.%ld numhalvings.%d magicExtra.%u\n",__func__,nHeight,curEra,ASSETCHAINS_LASTERA,subsidy,numhalvings,magicExtra);
return(subsidy);
}
@@ -1798,6 +1818,7 @@ void komodo_args(char *argv0)
printf("ASSETCHAINS_LASTERA, if specified, must be between 1 and %u. ASSETCHAINS_LASTERA set to %lu\n", ASSETCHAINS_MAX_ERAS, ASSETCHAINS_LASTERA);
}
ASSETCHAINS_LASTERA -= 1;
fprintf(stderr,"%s: lastEra=%lu maxEras=%d\n", __func__, ASSETCHAINS_LASTERA, ASSETCHAINS_MAX_ERAS);
ASSETCHAINS_TIMELOCKGTE = (uint64_t)GetArg("-ac_timelockgte", _ASSETCHAINS_TIMELOCKOFF);
ASSETCHAINS_TIMEUNLOCKFROM = GetArg("-ac_timeunlockfrom", 0);
@@ -1805,13 +1826,33 @@ void komodo_args(char *argv0)
if ( ASSETCHAINS_TIMEUNLOCKFROM > ASSETCHAINS_TIMEUNLOCKTO )
{
printf("ASSETCHAINS_TIMELOCKGTE - must specify valid ac_timeunlockfrom and ac_timeunlockto\n");
ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF;
ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF;
ASSETCHAINS_TIMEUNLOCKFROM = ASSETCHAINS_TIMEUNLOCKTO = 0;
}
Split(GetArg("-ac_end",""), sizeof(ASSETCHAINS_ENDSUBSIDY)/sizeof(*ASSETCHAINS_ENDSUBSIDY), ASSETCHAINS_ENDSUBSIDY, 0);
Split(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0);
Split(GetArg("-ac_halving",""), sizeof(ASSETCHAINS_HALVING)/sizeof(*ASSETCHAINS_HALVING), ASSETCHAINS_HALVING, 0);
Split(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0);
bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false;
if(ishush3) {
fprintf(stderr,"Setting custom HUSH3 chain values...\n");
// Over-ride HUSH3 values from CLI params. Changing our blocktime to 75s changes things
ASSETCHAINS_REWARD[0] = 0;
ASSETCHAINS_REWARD[1] = 1125000000;
ASSETCHAINS_REWARD[2] = 281250000; // 2.8125 HUSH goes to miners per block after 1st halving at Block 340K
ASSETCHAINS_REWARD[3] = 140625000; // 1.40625 HUSH after 2nd halving at Block 2020000
ASSETCHAINS_HALVING[0] = 129;
ASSETCHAINS_HALVING[1] = GetArg("-z2zheight",340000);
ASSETCHAINS_HALVING[2] = 2020000; // 2020000 = 340000 + 1680000 (1st halving block plus new halving interval)
ASSETCHAINS_HALVING[3] = 3700000; // ASSETCHAINS_HALVING[2] + 1680000;
ASSETCHAINS_ENDSUBSIDY[0] = 129;
ASSETCHAINS_ENDSUBSIDY[1] = GetArg("-z2zheight",340000);
ASSETCHAINS_ENDSUBSIDY[2] = 2*5422111; // TODO: Fix this, twice the previous end of rewards is an estimate
// TODO: fill in all possible values for each halving/reward interval
// based on simple halving schedule
}
Split(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0);
Split(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0);

View File

@@ -2406,45 +2406,10 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW)
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
{
fprintf(stderr,"%s: ht.%d\n", __func__, nHeight);
int32_t numhalvings,i; uint64_t numerator; CAmount nSubsidy = 3 * COIN;
if ( ASSETCHAINS_SYMBOL[0] == 0 )
{
if ( nHeight == 1 )
return(100000000 * COIN); // ICO allocation
else if ( nHeight < KOMODO_ENDOFERA )
return(3 * COIN);
else if ( nHeight < 2*KOMODO_ENDOFERA )
return(2 * COIN);
else return(COIN);
}
else
{
return(komodo_ac_block_subsidy(nHeight));
}
/*
// Mining slow start
// The subsidy is ramped up linearly, skipping the middle payout of
// MAX_SUBSIDY/2 to keep the monetary curve consistent with no slow start.
if (nHeight < consensusParams.nSubsidySlowStartInterval / 2) {
nSubsidy /= consensusParams.nSubsidySlowStartInterval;
nSubsidy *= nHeight;
return nSubsidy;
} else if (nHeight < consensusParams.nSubsidySlowStartInterval) {
nSubsidy /= consensusParams.nSubsidySlowStartInterval;
nSubsidy *= (nHeight+1);
return nSubsidy;
}
assert(nHeight > consensusParams.SubsidySlowStartShift());
int halvings = (nHeight - consensusParams.SubsidySlowStartShift()) / consensusParams.nSubsidyHalvingInterval;*/
// Force block reward to zero when right shift is undefined.
//int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;
//if (halvings >= 64)
// return 0;
// Subsidy is cut in half every 840,000 blocks which will occur approximately every 4 years.
//nSubsidy >>= halvings;
//return nSubsidy;
return komodo_ac_block_subsidy(nHeight);
}
bool IsInitialBlockDownload()

View File

@@ -200,7 +200,7 @@ UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk)
"2. \"label\" (string, optional, default=\"\") An optional label\n"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
"4. height (integer, optional, default=0) start at block height?\n"
"5. secret_key (integer, optional, default=188) used to import WIFs of other coins\n"
"5. secret_key (integer, optional, default=188) decimal value used to import WIFs of other coins\n"
"\nNote: This call can take minutes to complete if rescan is true.\n"
"\nExamples:\n"
"\nDump a private key\n"

View File

@@ -59,6 +59,7 @@ using namespace libzcash;
/**
* Settings
*/
const char * DEFAULT_WALLET_DAT = "wallet.dat";
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
@@ -668,6 +669,25 @@ void CWallet::Flush(bool shutdown)
bool CWallet::Verify(const string& walletFile, string& warningString, string& errorString)
{
LogPrintf("Using wallet %s\n", walletFile);
uiInterface.InitMessage(_("Verifying wallet..."));
if (walletFile != boost::filesystem::basename(walletFile) + boost::filesystem::extension(walletFile)) {
boost::filesystem::path path(walletFile);
if (path.is_absolute()) {
if (!boost::filesystem::exists(path.parent_path())) {
LogPrintf("Absolute path %s does not exist!", walletFile);
return false;
}
} else {
boost::filesystem::path full_path = GetDataDir() / path;
if (!boost::filesystem::exists(full_path.parent_path())) {
LogPrintf("Relative path %s does not exist!", walletFile);
return false;
}
}
}
if (!bitdb.Open(GetDataDir()))
{
// try moving the database env out of the way

View File

@@ -100,6 +100,8 @@ static const unsigned int DEFAULT_TX_RETENTION_LASTTX = 200;
//Amount of transactions to delete per run while syncing
static const int MAX_DELETE_TX_SIZE = 50000;
extern const char * DEFAULT_WALLET_DAT;
class CBlockIndex;
class CCoinControl;
class COutput;