Commit 2aa29500 authored by Éloïs's avatar Éloïs
Browse files

[feat] oxyde scrypt

parent fe055f94
......@@ -33,19 +33,18 @@ export const KeypairDependency = {
desc: "Password to generate the keypair",
},
{
value: "--keyN <N>",
desc:
"Scrypt `N` CPU/memory cost parameter. Must be a power of 2. Defaults to 4096.",
value: "--scrypt-log-n <log_n>",
desc: "Scrypt `log(n)` CPU/memory cost parameter. Defaults to 12.",
parser: parseInt,
},
{
value: "--keyr <r>",
value: "--scrypt-r <r>",
desc:
"Scrypt `r` The blocksize parameter, which fine-tunes sequential memory read size and performance. Defaults to 16.",
parser: parseInt,
},
{
value: "--keyp <p>",
value: "--scrypt-p <p>",
desc: "Scrypt `p` Parallelization parameter. Defaults to 1.",
parser: parseInt,
},
......@@ -99,11 +98,11 @@ export const KeypairDependency = {
confDAL: any
) => {
if (
(program.keyN || program.keyr || program.keyp) &&
(program.scryptLogN || program.scryptR || program.scryptP) &&
!(program.salt && program.passwd)
) {
throw Error(
"Missing --salt and --passwd options along with --keyN|keyr|keyp option"
"Missing --salt and --passwd options along with --scrypt-log-n|scrypt-r|scrypt-p option"
);
}
......
......@@ -11,8 +11,7 @@
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
import * as crypto from "crypto";
import { KeyPairBuilder, seedToSecretKey } from "../../../../neon/lib";
import { KeyPairBuilder, scrypt, seedToSecretKey } from "../../../../neon/lib";
const SEED_LENGTH = 32; // Length of the key
......@@ -20,7 +19,7 @@ const SEED_LENGTH = 32; // Length of the key
* Generates a new keypair object from salt + password strings.
* @param salt
* @param key
* @param N Scrypt parameter N. Defaults to 4096.
* @param log_n Scrypt parameter log n. Defaults to 12.
* @param r Scrypt parameter r. Defaults to 16.
* @param p Scrypt parameter p. Defaults to 1.
* @return keyPair An object containing the public and private keys, base58 encoded.
......@@ -28,28 +27,14 @@ const SEED_LENGTH = 32; // Length of the key
export const Scrypt = async (
salt: string,
key: string,
N = 4096,
log_n = 12,
r = 16,
p = 1
) => {
const res: { pub: string; sec: string } = await new Promise(
(resolve, reject) => {
crypto.scrypt(
key,
salt,
SEED_LENGTH,
{ N, r, p },
(err: any, seed: Buffer) => {
if (err) return reject(err);
const pair = KeyPairBuilder.fromSeed(seed);
resolve({
pub: pair.getPublicKey(),
sec: seedToSecretKey(seed),
});
}
);
}
);
const seed = scrypt(salt, key, log_n, r, p);
return res;
return {
pub: KeyPairBuilder.fromSeed(seed).getPublicKey(),
sec: seedToSecretKey(seed),
};
};
export { Ed25519Signator, generateRandomSeed, seedToSecretKey, sha256, verify, Wot } from "../native";
export { Ed25519Signator, generateRandomSeed, seedToSecretKey, scrypt, sha256, verify, Wot } from "../native";
export { KeyPairBuilder } from "./crypto";
export { WotBuilder } from "./wot";
......@@ -11,5 +11,6 @@ export class Ed25519Signator {
export function generateRandomSeed(): Buffer;
export function seedToSecretKey(seed: Buffer): string;
export function scrypt(salt: string, password: string, log_n: number, r: number, p: number): Buffer;
export function sha256(data: string): string;
export function verify(message: Buffer | string, sig: string, pubkey: string): boolean;
......@@ -6,6 +6,7 @@ import * as _wot from './wot';
export import Ed25519Signator = _crypto.Ed25519Signator;
export import generateRandomSeed = _crypto.generateRandomSeed;
export import seedToSecretKey = _crypto.seedToSecretKey;
export import scrypt = _crypto.scrypt;
export import sha256 = _crypto.sha256;
export import verify = _crypto.verify;
......
......@@ -13,13 +13,13 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::into_neon_res;
use crate::{create_js_buffer, into_neon_res};
use dup_crypto::bases::b58::ToBase58;
use dup_crypto::hashs::Hash;
use dup_crypto::keys::{
ed25519::{
Ed25519KeyPair, KeyPairFromSeed32Generator, PublicKey as Ed25519PublicKey,
Signator as Ed25519Signator, Signature as Ed25519Signature,
Ed25519KeyPair, KeyPairFromSaltedPasswordGenerator, KeyPairFromSeed32Generator,
PublicKey as Ed25519PublicKey, Signator as Ed25519Signator, Signature as Ed25519Signature,
},
KeyPair, PublicKey, Signator, Signature,
};
......@@ -34,14 +34,7 @@ pub fn generate_random_seed(mut cx: FunctionContext) -> JsResult<JsBuffer> {
Seed32::random().map_err(|_| "fail to generate random seed"),
)?;
let mut js_buffer = JsBuffer::new(&mut cx, 32)?;
cx.borrow_mut(&mut js_buffer, |data| {
let slice = data.as_mut_slice::<u8>();
slice.copy_from_slice(seed.as_ref());
});
Ok(js_buffer)
create_js_buffer(&mut cx, seed.as_ref())
}
pub fn seed_to_expanded_base58_secret_key(mut cx: FunctionContext) -> JsResult<JsString> {
......@@ -62,6 +55,19 @@ pub fn seed_to_expanded_base58_secret_key(mut cx: FunctionContext) -> JsResult<J
Ok(cx.string(expanded_base58_secret_key))
}
pub fn scrypt(mut cx: FunctionContext) -> JsResult<JsBuffer> {
let salt = cx.argument::<JsString>(0)?.value();
let password = cx.argument::<JsString>(1)?.value();
let log_n = cx.argument::<JsNumber>(2)?.value() as u8;
let r = cx.argument::<JsNumber>(3)?.value() as u32;
let p = cx.argument::<JsNumber>(4)?.value() as u32;
let seed = KeyPairFromSaltedPasswordGenerator::with_parameters(log_n, r, p)
.generate_seed(password.as_bytes(), salt.as_bytes());
create_js_buffer(&mut cx, seed.as_ref())
}
pub fn sha256(mut cx: FunctionContext) -> JsResult<JsString> {
let str_datas = cx.argument::<JsString>(0)?.value();
Ok(cx.string(Hash::compute_str(&str_datas).to_hex().to_uppercase()))
......
......@@ -18,6 +18,17 @@ mod wot;
use neon::{prelude::*, register_module};
fn create_js_buffer<'c, C: Context<'c>>(context: &mut C, bytes: &[u8]) -> JsResult<'c, JsBuffer> {
let mut js_buffer = unsafe { JsBuffer::uninitialized(context, bytes.len() as u32)? };
context.borrow_mut(&mut js_buffer, |data| {
let slice = data.as_mut_slice::<u8>();
slice.copy_from_slice(bytes);
});
Ok(js_buffer)
}
fn into_neon_res<'c, C: Context<'c>, T, S: AsRef<str>>(
context: &mut C,
rust_result: Result<T, S>,
......@@ -34,6 +45,7 @@ register_module!(mut cx, {
"seedToSecretKey",
crate::crypto::seed_to_expanded_base58_secret_key,
)?;
cx.export_function("scrypt", crate::crypto::scrypt)?;
cx.export_function("sha256", crate::crypto::sha256)?;
cx.export_function("verify", crate::crypto::verify)?;
cx.export_class::<crate::crypto::JsKeyPair>("Ed25519Signator")?;
......
......@@ -87,9 +87,9 @@ direct_webstart \
--at \
--salt \
--passwd \
--keyN \
--keyr \
--keyp \
--scrypt-log-n \
--scrypt-r \
--scrypt-p \
--keyprompt \
--keyfile \
--nointeractive \
......
......@@ -23,12 +23,12 @@ describe('Module usage', () => {
try {
const stack = Statics.minimalStack();
stack.registerDependency(KeypairDependency, 'duniter-keypair');
await stack.executeStack(['node', 'index.js', 'config', '--memory', '--keyN', '2048']);
await stack.executeStack(['node', 'index.js', 'config', '--memory', '--scrypt-log-n', '2048']);
} catch (e) {
errMessage = e.message;
}
should.exist(errMessage);
should.equal(errMessage, 'Missing --salt and --passwd options along with --keyN|keyr|keyp option');
should.equal(errMessage, 'Missing --salt and --passwd options along with --scrypt-log-n|scrypt-r|scrypt-p option');
})
it('no options on brand new node should generate random key', async () => {
......
"use strict";
import { Ed25519Signator, KeyPairBuilder, sha256, verify, generateRandomSeed, seedToSecretKey } from "../../neon/lib";
import { Ed25519Signator, KeyPairBuilder, scrypt, sha256, verify, generateRandomSeed, seedToSecretKey } from "../../neon/lib";
import * as assert from "assert";
......@@ -17,6 +17,18 @@ describe('ed25519 tests:', function(){
//assert.equal(rawSec, '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP');
})
it('scrypt 7iMV3b6j2hSj5WtrfchfvxivS9swN3opDgxudeHq64fb', function(done){
const seed = scrypt(
"JhxtHB7UcsDbA9wMSyMKXUzBZUQvqVyB32KwzS9SWoLkjrUhHV",
"JhxtHB7UcsDbA9wMSyMKXUzBZUQvqVyB32KwzS9SWoLkjrUhHV_",
12,
16,
1);
let pub = KeyPairBuilder.fromSeed(seed).getPublicKey();
assert.equal(pub, "7iMV3b6j2hSj5WtrfchfvxivS9swN3opDgxudeHq64fb")
done();
});
it('sha256 hello', function(done){
const msg = "hello";
const hash = sha256(msg);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment