GithubHelp home page GithubHelp logo

grempe / secrets.js Goto Github PK

View Code? Open in Web Editor NEW

This project forked from amper5and/secrets.js

280.0 280.0 73.0 828 KB

Secret sharing for javascript

License: MIT License

JavaScript 96.18% HTML 3.82%

secrets.js's Introduction

Hi there, I'm Glenn - aka @grempe ๐Ÿ‘‹

Twitter Follow

I'm a Husband, Father, Developer, and the Founder & CEO of Truestamp (on GitHub @truestamp)!!

  • ๐ŸŒฑ Iโ€™m currently growing Truestamp ๐Ÿคฃ
  • ๐Ÿ‘ฏ Iโ€™m focused on the intersection of Privacy, Security, Cryptography, and Integrity
  • ๐Ÿฅ… Goals: Help my customers verify the integrity of their most important data
  • โšก Fun fact: My vehicle license plate has a cryptography reference. I think it confuses most who see it

Connect with me


GitHub Stats


Truestamp's GitHub stats

Top Langs

secrets.js's People

Contributors

amper5and avatar codesleuth avatar dependabot-preview[bot] avatar grempe avatar rlaace423 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

secrets.js's Issues

`radix` doesn't appear used, as bin2hex is hard-coded to 16

I'm unclear on what the radix is used for, since bin2hex is hard-coded to use 16 as the radix. How can I get output that is base 36 encoded?

I tried playing around with various parts of the code, changing 16 -> radix, but not having much luck.

share(): Error: Invalid hex character

I have a project of an end-to-end verifiable online voting system. I generated the private key for encryption using the node-seal library available online. I was trying to split the private key into multiple shares using Shamir's threshold secret sharing scheme. The secret key i generated is in base64string format. When trying to split the key I had to first covert it into hex which went fine but when I tried to split the key I got the following error:

> Error: Invalid hex character.
at hex2bin (/home/shabeeh/node_modules/secrets.js/secrets.js:458:10)
at Object.exports.share (/home/shabeeh/node_modules/secrets.js/secrets.js:229:17)
at /home/shabeeh/iMatter/iMatter-Web/server/SplitKey.js:75:30 Error: Invalid hex character.
at hex2bin (/home/shabeeh/node_modules/secrets.js/secrets.js:458:10)
at Object.exports.share (/home/shabeeh/node_modules/secrets.js/secrets.js:229:17)
at /home/shabeeh/iMatter/iMatter-Web/server/SplitKey.js:75:30
/home/shabeeh/iMatter/iMatter-Web/node_modules/node-seal/dist/seal.node.js:1

!function(A,I){if("object"==typeof exports&&"object"==typeof module)module.exports=I();else if("function"==typeof define&&define.amd)define([],I);else{var g=I();for(var C in g)("object"==typeof exports?exports:A)[C]=g[C]}}("undefined"!=typeof self?self:this,(function(){return function(A){var I={};function g(C){if(I[C])return I[C].exports;var B=I[C]={i:C,l:!1,exports:{}};return A[C].call(B.exports,B,B.exports,g),B.l=!0,B.exports}return g.m=A,g.c=I,g.d=function(A,I,C){g.o(A,I)||Object.defineProperty(A,I,{enumerable:!0,get:C})},g.r=function(A){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(A,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(A,"__esModule",{value:!0})},g.t=function(A,I){if(1&I&&(A=g(A)),8&I)return A;if(4&I&&"object"==typeof A&&A&&A.__esModule)return A;var C=Object.create(null);if(g.r(C),Object.defineProperty(C,"default",{enumerable:!0,value:A}),2&I&&"string"!=typeof A)for(var B in A)g.d(

RuntimeError: abort(Error: Invalid hex character.). Build with -s ASSERTIONS=1 for more info.
at process.IA (/home/shabeeh/iMatter/iMatter-Web/node_modules/node-seal/dist/seal.node.js:1:5494)
at process.emit (events.js:198:13)
at emitPromiseRejectionWarnings (internal/process/promises.js:140:18)
at process._tickCallback (internal/process/next_tick.js:69:34)

I am unable to understand where the problem occurred because the string was converted to hex form, i verified it using console.log().

I am new to nodejs and I am extremely sorry if the question is dumb but I am stuck at it and would appreciate any help

Alternative Primitive Polynomial

First, thanks for the library! This has been very helpful!

I'm interested in using a different primitive polynomial and, while I'm able to get most alternatives to work, I'm having trouble getting Rijndael's polynomial to work: x^8 + x^4 + x^3 + x + 1 -> 283 -> 27. The initialization process fails to build the log table correctly, it seems. The resulting table has a large portion of null values.

I've tried a simple approach of replacing the primitive polynomial in defaults.primitivePolynomials[8] with 27 (or 283).

I've tried using other primitive polynomials with this approach and it has worked. I was able to generate shares and recover them successfully.

Here are some alternative polynomials that I've tried and have worked as expected:
x^8 + x^4 + x^3 + x^2 + 1 -> 285
x^8 + x^5 + x^3 + x^1 + 1 -> 299
x^8 + x^6 + x^4 + x^3 + x^2 + x^1 + 1 -> 351
x^8 + x^6 + x^5 + x^1 + 1 -> 355
x^8 + x^6 + x^5 + x^2 + 1 -> 357
x^8 + x^6 + x^5 + x^3 + 1 -> 361
x^8 + x^7 + x^6 + x^1 + 1 -> 451
x^8 + x^7 + x^6 + x^5 + x^2 + x^1 + 1 -> 487

All of these are using the default 8 bits.

I expect that I'm doing something wrong or misunderstanding something fundamental about how this works.

Any thoughts or guidance on why it doesn't work or how to get it to work would be greatly appreciated!

Unnecessary ruling out of zero in (CS)PRNG

Thanks for your implementation. Since this is audited, I'm using it as a basis for a (simplified) Python implementation of my own. Nevertheless I don't understand one thing: why do you restrict the cryptographically secure pseudo-random number generator to spit out non-zero coefficients for the polynomials? This reduces the search space slightly by 1/2^bits for each coefficient (for large bits this is not an issue but it is for small bits (for bits=1 the algorithm would break down completely since the coefficients would always be equal to 1, but fortunately you only allow bits>=3)).

secrets.js/secrets.js

Lines 228 to 231 in 14a4b68

// return null so this result can be re-processed if the result is all 0's.
if ((str.match(/0/g) || []).length === str.length) {
return null
}

Here, the construct function returns null on all-zeros (i.e., the zero vector)

secrets.js/secrets.js

Lines 252 to 255 in 14a4b68

while (str === null) {
buf = crypto.randomBytes(bytes)
str = construct(bits, buf.toString("hex"), radix, size)
}

secrets.js/secrets.js

Lines 273 to 280 in 14a4b68

while (str === null) {
str = construct(
bits,
crypto.getRandomValues(new Uint32Array(elems)),
radix,
size
)
}

In these two, you keep generating new PRNG numbers until they are not the zero vector. For bits=3 this means that the only coefficients allowed are $1, 2, 3, \ldots, 7 \in GF(8)$, but not 0.

Publish 1.2.0?

Currently, the latest release published to NPM is 1.1.0, which doesn't include secrets.seedRNG() API from the master branch (which is marked 1.2.0 in package.json).

Is there any reason 1.2.0 is not published? Maybe it's worth publishing it?

Module init fails in a typescript project

Hi there, thanks for sharing & maintaining this library!

I try to use the library in a fresh create-react-app project with Typescript enabled. I get the following error:

secrets.js:456 Uncaught Error: Initialization failed.
    at Object.init (secrets.js:456)
    at secrets.js:828
    at Object.<anonymous> (secrets.js:29)
    at secrets.js:31
    at Object../node_modules/secrets.js-grempe/secrets.js (secrets.js:41)
    at __webpack_require__ (bootstrap:790)
    at fn (bootstrap:150)
    at Module../src/state/index.ts (index.ts:7)
    at __webpack_require__ (bootstrap:790)
    at fn (bootstrap:150)
    at Module../src/App.tsx ( groupOptions: {} namespace object:25)
    at __webpack_require__ (bootstrap:790)
    at fn (bootstrap:150)
    at Module../src/index.tsx (App.tsx:51)
    at __webpack_require__ (bootstrap:790)
    at fn (bootstrap:150)
    at Object.0 (variables.css?6ef5:37)
    at __webpack_require__ (bootstrap:790)
    at checkDeferredModules (bootstrap:45)
    at Array.webpackJsonpCallback [as push] (bootstrap:32)
    at main.chunk.js:1

I tried with:

import * as secrets from 'secrets.js-grempe';
import secrets from 'secrets.js-grempe';
const secrets = require('secrets.js-grempe');

and got the same error.

A global script balise works (<script src="/secrets.js"></script>).

Shares are larger than original data

Hi, really enjoying using this library!

The readme states that the shares are "each the same size in bits as the original secret". This doesn't appear to be true.

console.log(secrets.random(256).length, secrets.random(512).length) // => 64, 128
console.log(
  secrets.share(secrets.random(256), 10, 5)[0].length,
  secrets.share(secrets.random(512), 10, 5)[0].length
) // => 99, 163

I guess that the actual "value" of the share is the final X bytes where X is the secret size, but you still need all those extra bytes to actually restore the secret, right?

results from combining(a) and (a,b) are the same

if you combine(a) and then combine(a,b) where a is a valid share and b an invalid share, the returned result appears to be the same. This is unexpected, for me at least ;)

Also, the result of a failed combine() does not seem to return strings.

(function() {
    var secrets = require('secrets.js-grempe');

    var seal = function(secret) {

        return new Promise(function(resolve,reject) {
            var hex = secrets.str2hex(secret);

            var shares = secrets.share(hex,5,3,256);

            resolve(shares);
        });
    };

    var unseal_A = function(shares) {
        var suppliedKeys = [];

        return new Promise(function(resolve,reject) {
            shares.forEach(function(share,index) {
                suppliedKeys.push(share);

                var result = secrets.hex2str(secrets.combine(suppliedKeys));

                console.log("unseal_A",index,result);
            });

            resolve();
        });

    };

    var unseal_B = function(shares) {
        var suppliedKeys = [];

        return new Promise(function(resolve,reject) {
            shares.forEach(function(share,index) {

                var dummy = [];

                suppliedKeys.push(share);

                /** so at this point, if we are under the threshold, creating a new share should result in garbage
                 *
                 *  if, however, we are at the threshold, creating a new share should result in a vaild share, and
                 *  valid shares pushed into a combine() would always return a secret
                 *
                 *  invalid shares pushed into a combine() should return garbage
                 *
                 *  so the theory was that if we are at a threshold, and add another valid key, the results of combine(suppliedKeys)
                 *  and combine(suppliedKeys + newShare) would be the same, and therefore we would know that both the threshold
                 *  has been reached and the key decrypted
                 *
                 *  however, it seems that calling combine() with arrayA and ArrayA + another share also returns the same result
                 *  just am invalid one :(
                 */

                dummy.push(secrets.newShare( index + 1, suppliedKeys ));

                var resultA = secrets.hex2str(secrets.combine(suppliedKeys));
                var resultB = secrets.hex2str(secrets.combine(suppliedKeys.concat(dummy)));

                console.log("unseal_B",index,resultA,resultB,resultA === resultB);
            });

            resolve();
        });

    };

    seal("foo123").then(function(keys) {

        return unseal_A(keys).then(function() {

        })

        .then(function() {
            return unseal_B(keys);
        });

    });

})();

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.