From a5677ca0866814f9724dbba80c4211dc097a278f Mon Sep 17 00:00:00 2001
From: "[1000i100] Millicent Billette" <git@1000i100.fr>
Date: Sun, 4 Apr 2021 05:51:57 +0200
Subject: [PATCH] WiP: sign

---
 CI/gen-prod-test.js              |  2 +-
 npm/package.json                 |  6 +++++
 package-lock.json                |  6 ++---
 package.json                     | 17 +++++++++----
 src/basex.mjs                    |  3 +++
 src/crypto.mjs                   | 42 ++++++++++++++++++++++++++------
 src/crypto.test.mjs              | 23 ++++++++++++++---
 src/data-pod-client.mjs          |  1 +
 src/data-pod-client.test-e2e.mjs |  3 +--
 src/data-pod-client.test.mjs     |  7 ++++++
 src/gva-client.mjs               |  1 +
 src/gva-client.test-e2e.mjs      |  6 +++++
 src/gva-client.test.js           |  0
 src/gva-client.test.mjs          |  6 +++++
 src/multi-node-layer.mjs         |  1 +
 src/multi-node-layer.test.mjs    |  6 +++++
 16 files changed, 108 insertions(+), 22 deletions(-)
 delete mode 100644 src/gva-client.test.js
 create mode 100644 src/gva-client.test.mjs

diff --git a/CI/gen-prod-test.js b/CI/gen-prod-test.js
index 0c1e11a..ca517f6 100644
--- a/CI/gen-prod-test.js
+++ b/CI/gen-prod-test.js
@@ -3,7 +3,7 @@ const fs = require('fs');
 fs.readdirSync('src/').forEach(fileName => {
 	const orgContent = fs.readFileSync(`src/${fileName}`, 'utf8').replace(/from '\.\.\//g, 'from \'../../');
 	fs.writeFileSync(`generated/cov-env/${fileName}`, orgContent);
-	if (!fileName.includes('.test.')) return;
+	if (!fileName.includes('.test')) return;
 	fs.writeFileSync(`generated/minified/${fileName}`, orgContent);
 	const allJsTest = orgContent.replace(
 		/import \* as app from '\.\/(crypto)\.mjs';/,
diff --git a/npm/package.json b/npm/package.json
index e9464db..73e07b7 100644
--- a/npm/package.json
+++ b/npm/package.json
@@ -19,5 +19,11 @@
   "bugs": {
     "url": "https://framagit.org/g1/g1lib.js/-/issues"
   },
+	"ava": {
+		"files": [
+			"**/*.test*.mjs",
+			"*.test*.mjs"
+		]
+	},
   "license": "AGPL-3.0"
 }
diff --git a/package-lock.json b/package-lock.json
index 1157bee..766f58f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -871,9 +871,9 @@
       "dev": true
     },
     "ansi-styles": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.1.0.tgz",
-      "integrity": "sha512-osxifZo3ar56+e8tdYreU6p8FZGciBHo5O0JoDAxMUqZuyNUb+yHEwYtJZ+Z32R459jEgtwVf1u8D7qYwU0l6w==",
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+      "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
       "dev": true
     },
     "anymatch": {
diff --git a/package.json b/package.json
index 34edaf8..1e7412d 100644
--- a/package.json
+++ b/package.json
@@ -28,8 +28,8 @@
 		"test:production:duplication": "jscpd ./",
 		"test:production:complexity": "./node_modules/.bin/es6-plato -r -d generated/maintainability ./src/*",
 		"test:production:complexity:badgesAndThreshold": "node CI/plato-badges.js",
-		"test:production:srcCoverage": "cd generated/cov-env/ && c8 ava",
-		"test:production:testMinified": "cd generated/minified/ && ava",
+		"test:production:srcCoverage": "cd generated/cov-env/ && c8 ava **.test.mjs",
+		"test:production:testMinified": "cd generated/minified/ && ava **.test.mjs",
 		"test:production:test-e2e": "cd generated/minified/ && ava **.test-e2e.mjs",
 		"test:production:clean": "rm -rf generated/minified/*.test*.mjs",
 		"test:production:minified2npm": "cp -rf generated/minified/* generated/npm/",
@@ -37,10 +37,10 @@
 		"watch2null": "chokidar src/* -c \"npm run test:dev:runTests 2>/dev/null\""
 	},
 	"dependencies": {
+		"js-sha256": "https://github.com/1000i100/js-sha256#master",
 		"latinize-to-ascii": "^0.5.2",
 		"scrypt-async-modern": "^3.0.12",
-		"tweetnacl": "^1.0.3",
-		"js-sha256": "https://github.com/1000i100/js-sha256#master"
+		"tweetnacl": "^1.0.3"
 	},
 	"devDependencies": {
 		"@jscpd/badge-reporter": "^3.3.23",
@@ -58,10 +58,17 @@
 		"xo": "^0.38.2"
 	},
 	"disabledDependenciesTODOAddComplexityQualityCheck": {
+		"noble-ed25519": "https://github.com/1000i100/noble-ed25519#master",
 		"ecma-nacl": "^2.5.0",
 		"codehawk-cli": "^6.0.3"
 	},
-	"ava": {},
+	"ava": {
+		"files": [
+			"**/*.test*.mjs",
+			"*.test*.mjs",
+			"!node_modules"
+		]
+	},
 	"c8": {
 		"all": true,
 		"branches": 0.08,
diff --git a/src/basex.mjs b/src/basex.mjs
index 146fada..6f011a5 100644
--- a/src/basex.mjs
+++ b/src/basex.mjs
@@ -1,5 +1,8 @@
 // Inspired by bs58, base-x then @thi.ng/base-n module
 const B58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
+const B64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
+
+export const b64 = basex(B64_ALPHABET);
 export const b58 = basex(B58_ALPHABET);
 export const b16 = basex('0123456789abcdef');
 export default basex;
diff --git a/src/crypto.mjs b/src/crypto.mjs
index 993af3b..f662b16 100644
--- a/src/crypto.mjs
+++ b/src/crypto.mjs
@@ -1,7 +1,8 @@
 // Alt deps :  import {generate_keypair} from "ecma-nacl/build/lib/signing/sign.js";
 // Alt deps :  import scrypt from "ecma-nacl/build/lib/scrypt/scrypt.js";
 import nacl from '../generated/vendors/nacl.mjs';
-import {b58} from './basex.mjs';
+// Alt import * as ed25519 from '../node_modules/noble-ed25519/index.mjs';
+import {b58,b64} from './basex.mjs';
 
 export {b58};
 import sha from '../node_modules/js-sha256/src/sha256.mjs';
@@ -13,12 +14,10 @@ import scrypt from '../generated/vendors/scrypt.mjs';
 
 export async function idSecPass2rawAll(idSec, pass) {
 	const rawSeed = await saltPass2seed(idSec, pass);
-	const keyPair = seed2keyPair(rawSeed);
-	return {
-		seed: rawSeed,
-		publicKey: keyPair.publicKey,
-		secretKey: keyPair.secretKey
-	};
+	const keyPair = await seed2keyPair(rawSeed);
+	keyPair.seed = rawSeed;
+	keyPair.pubKey = keyPair.publicKey;
+	return keyPair;
 }
 
 export function raw2b58(raws) {
@@ -35,7 +34,19 @@ export async function idSecPass2cleanKeys(idSec, pass) {
 export function seed2keyPair(seed) {
 	return generateKeypair(seed);
 }
-
+/* Noble edition
+export async function seed2keyPair(rawSeed) {
+	const pubKey = await ed25519.getPublicKey(rawSeed);
+	console.log('pubKey',pubKey);
+	const naclLikePrivateKey = new Uint8Array(64);
+	naclLikePrivateKey.set(rawSeed);
+	naclLikePrivateKey.set(pubKey,32);
+	return {
+		publicKey:pubKey,
+		secretKey:naclLikePrivateKey
+	};
+}
+*/
 export async function saltPass2seed(idSec, pass) {
 	const options = {
 		logN: 12,
@@ -79,6 +90,12 @@ export function b58pubKey2bin(b58pubKey) {
 	binPubKey.set(decoded, 32 - decoded.length);
 	return binPubKey;
 }
+export function b58secretKey2bin(b58secretKey) {
+	const binSecretKey = new Uint8Array(64);
+	const decoded = b58.decode(b58secretKey);
+	binSecretKey.set(decoded, 64 - decoded.length);
+	return binSecretKey;
+}
 
 export function checkKey(pubKeyWithChecksum) {
 	const part = pubKeyWithChecksum.split(':');
@@ -94,3 +111,12 @@ export function checkKey(pubKeyWithChecksum) {
 	if (pubKey2checksum(b58pubKey, true, true, false) === checkSum) return true;
 	throw new Error('Bad checksum');
 }
+
+export function sign(unsignedDocument,secretKey){
+	const encoder = new TextEncoder();
+	const decoder = new TextDecoder();
+	const rawSign = nacl.sign.detached(encoder.encode(unsignedDocument.trim()), b58secretKey2bin(secretKey));
+	const b64Sign = b64.encode(rawSign);
+
+	return `${unsignedDocument.trim()}\n${b64Sign}`;
+}
diff --git a/src/crypto.test.mjs b/src/crypto.test.mjs
index 378e09c..61eac96 100644
--- a/src/crypto.test.mjs
+++ b/src/crypto.test.mjs
@@ -1,6 +1,5 @@
 import test from 'ava';
 import * as app from './crypto.mjs';
-import {b58} from "./crypto.mjs";
 
 const idSec = 'a';
 const mdp = 'b';
@@ -8,6 +7,24 @@ const mdp = 'b';
 const pubKey = 'AoxVA41dGL2s4ogMNdbCw3FFYjFo5FPK36LuiW1tjGbG';
 const secretKey = '3ZsmZhnRv137dS1s7Q3jFGKLTDyhkwguPHfnWBxzDCTTHKWGnYw9zBk3gcCUJCc72TEUuyzM7cqpo7c5LYhs1Qtv';
 const seed = '9eADqX8V6VcPdJCHCVYiE1Vnift9nFNrvr9aTaXA5RJc';
+const unsignedDocument = `
+Version: 10
+Type: Identity
+Currency: duniter_unit_test_currency
+Issuer: AoxVA41dGL2s4ogMNdbCw3FFYjFo5FPK36LuiW1tjGbG
+UniqueID: tic
+Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
+`;
+const signedDocument = `
+Version: 10
+Type: Identity
+Currency: duniter_unit_test_currency
+Issuer: AoxVA41dGL2s4ogMNdbCw3FFYjFo5FPK36LuiW1tjGbG
+UniqueID: tic
+Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
+???
+`;
+test.skip('sign document', async t => t.is(await app.sign(unsignedDocument,secretKey), signedDocument));
 
 test('b58 should decode/encode well', t => t.is(app.b58.encode(app.b58.decode(pubKey)), pubKey));
 test('b58 on pubKey with leading 1', t => t.is(app.b58.encode(app.b58.decode('12BjyvjoAf5qik7R8TKDJAHJugsX23YgJGi2LmBUv2nx')), '12BjyvjoAf5qik7R8TKDJAHJugsX23YgJGi2LmBUv2nx'));
@@ -16,9 +33,9 @@ test('b58 on pubKey without leading 1', t => t.is(app.b58.encode(app.b58.decode(
 test('saltPass2seed should convert salt & password to seed with scrypt', async t => {
 	t.is(app.b58.encode(await app.saltPass2seed(idSec, mdp)), seed);
 });
-test('seed2keyPair should generate public and private key nacl/sodium way.', t => {
+test('seed2keyPair should generate public and private key nacl/sodium way.', async t => {
 	const rawSeed = app.b58.decode(seed);
-	const rawKeyPair = app.seed2keyPair(rawSeed);
+	const rawKeyPair = await app.seed2keyPair(rawSeed);
 	t.is(app.b58.encode(rawKeyPair.publicKey), pubKey);
 	t.is(app.b58.encode(rawKeyPair.secretKey), secretKey);
 });
diff --git a/src/data-pod-client.mjs b/src/data-pod-client.mjs
index e69de29..cb0ff5c 100644
--- a/src/data-pod-client.mjs
+++ b/src/data-pod-client.mjs
@@ -0,0 +1 @@
+export {};
diff --git a/src/data-pod-client.test-e2e.mjs b/src/data-pod-client.test-e2e.mjs
index 568ab59..807ea82 100644
--- a/src/data-pod-client.test-e2e.mjs
+++ b/src/data-pod-client.test-e2e.mjs
@@ -1,7 +1,7 @@
 import test from 'ava';
 import * as app from './data-pod-client.mjs';
 
-test('data-pod-client real server request', async t => {
+test.skip('data-pod-client real server request', async t => {
 	const hosts = ['https://g1.data.e-is.pro/'];
 	const query = 'user/profile/2sZF6j2PkxBDNAqUde7Dgo5x3crkerZpQ4rBqqJGn8QT?&_source=title';
 	const expectedResult = JSON.parse(`{
@@ -15,4 +15,3 @@ test('data-pod-client real server request', async t => {
 
 	t.is(result._source.title, expectedResult._source.title);
 });
-
diff --git a/src/data-pod-client.test.mjs b/src/data-pod-client.test.mjs
index e69de29..aab9fed 100644
--- a/src/data-pod-client.test.mjs
+++ b/src/data-pod-client.test.mjs
@@ -0,0 +1,7 @@
+import test from 'ava';
+import * as app from './data-pod-client.mjs';
+
+test('dummy', async t => {
+	t.true(true);
+});
+
diff --git a/src/gva-client.mjs b/src/gva-client.mjs
index e69de29..cb0ff5c 100644
--- a/src/gva-client.mjs
+++ b/src/gva-client.mjs
@@ -0,0 +1 @@
+export {};
diff --git a/src/gva-client.test-e2e.mjs b/src/gva-client.test-e2e.mjs
index e69de29..75c7f61 100644
--- a/src/gva-client.test-e2e.mjs
+++ b/src/gva-client.test-e2e.mjs
@@ -0,0 +1,6 @@
+import test from 'ava';
+import * as app from './gva-client.mjs';
+
+test('dummy', async t => {
+	t.true(true);
+});
diff --git a/src/gva-client.test.js b/src/gva-client.test.js
deleted file mode 100644
index e69de29..0000000
diff --git a/src/gva-client.test.mjs b/src/gva-client.test.mjs
new file mode 100644
index 0000000..75c7f61
--- /dev/null
+++ b/src/gva-client.test.mjs
@@ -0,0 +1,6 @@
+import test from 'ava';
+import * as app from './gva-client.mjs';
+
+test('dummy', async t => {
+	t.true(true);
+});
diff --git a/src/multi-node-layer.mjs b/src/multi-node-layer.mjs
index e69de29..cb0ff5c 100644
--- a/src/multi-node-layer.mjs
+++ b/src/multi-node-layer.mjs
@@ -0,0 +1 @@
+export {};
diff --git a/src/multi-node-layer.test.mjs b/src/multi-node-layer.test.mjs
index e69de29..5467eed 100644
--- a/src/multi-node-layer.test.mjs
+++ b/src/multi-node-layer.test.mjs
@@ -0,0 +1,6 @@
+import test from 'ava';
+import * as app from './multi-node-layer.mjs';
+
+test('dummy', async t => {
+	t.true(true);
+});
-- 
GitLab