Skip to content

Commit

Permalink
More readme and some endianness testing
Browse files Browse the repository at this point in the history
  • Loading branch information
poing committed Jan 22, 2024
1 parent 9b49c1f commit 910380c
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 2 deletions.
91 changes: 89 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,102 @@
[![codecov](https://codecov.io/gh/poing/JS2PySecrets/branch/main/graph/badge.svg?token=JS2PySecrets_token_here)](https://codecov.io/gh/poing/JS2PySecrets)
[![CI](https://github.com/poing/JS2PySecrets/actions/workflows/main.yml/badge.svg)](https://github.com/poing/JS2PySecrets/actions/workflows/main.yml)

Awesome js2pysecrets created by poing

This is a `Python` implementation of [Shamir's threshold secret sharing scheme](http://en.wikipedia.org/wiki/Shamir's_Secret_Sharing), based **and compatible with** the `JavaScript` fork of `secrets.js` [*maintained by `grempe`*](https://github.com/grempe/secrets.js). Which is orginally based on the code created by `amper5and` on Github. The [original secrets.js can be found there](https://github.com/amper5and/secrets.js/).

## Status

The project is intended to create a `Python` version that is compatible with `secrets.js`. It's currently in the **DEVELOPMENT** stage and the framework is being built to *effectively* test and run the `JavaScript` from within the `Python` environment.

All of the `JavaScript` functions can be called from *within* the `Python` environment. However, **there are limitations**! Most notably, you can **ONLY** call a single function, so some of the utility provided by the `JavaScript` version is not available. *In many cases, isn't even necessary*.

Combing of shares is not working *yet*...

### Requirements

The use this project in it's current state **and for testing**, `Node` is required on the system. This is used to run the `JavaScript`.
**`Node`** is **required**.

To use this project in it's current state **and for testing**, `Node` is required on the system. `Node` will always bee required for testing. It's used to run the `JavaScript` in the local environment.

## Examples

Divide a 512-bit key, expressed in hexadecimal form, into 10 shares, requiring that any 5 of them are necessary to reconstruct the original key:

**Not everything is working yet...**

```python
import json
import js2pysecrets

# generate a 512-bit key
# key = js2pysecrets.random(512) // => key is a hex string
key = js2pysecrets.random(512)
print(key)

# split into 10 shares with a threshold of 5
# shares = js2pysecrets.share(key, 10, 5)
# => shares = ['801xxx...xxx','802xxx...xxx','803xxx...xxx','804xxx...xxx','805xxx...xxx']
shares = js2pysecrets.share(key, 10, 5)
print(shares)

# // combine 4 shares
# var comb = secrets.combine(shares.slice(0, 4))
# console.log(comb === key) // => false
#
# // combine 5 shares
# comb = secrets.combine(shares.slice(4, 9))
# console.log(comb === key) // => true
#
# // combine ALL shares
# comb = secrets.combine(shares)
# console.log(comb === key) // => true
#
# // create another share with id 8
# var newShare = secrets.newShare(8, shares) // => newShare = '808xxx...xxx'
#
# // reconstruct using 4 original shares and the new share:
# comb = secrets.combine(shares.slice(1, 5).concat(newShare))
# console.log(comb === key) // => true
```

Divide a password containing a mix of numbers, letters, and other characters, requiring that any 3 shares must be present to reconstruct the original password:

**Things really start to break here...**
*Big and reversed endianness for the `JS` str2hex*

```python
import json
import js2pysecrets

# var pw = "<<PassWord123>>"
pw = "<<PassWord123>>"

# convert the text into a hex string
# jsHex = secrets.str2hex(pw) // => hex string
jsHex = js2pysecrets.str2hex(pw)
print(jsHex)

# Notice how the JS uses an unconventional str2hex method
pyHex = pw.encode('utf-16').hex().lstrip('fe') # Stripped off the BOM
print(pyHex)

# // split into 5 shares, with a threshold of 3
# var shares = secrets.share(pwHex, 5, 3)
#
# // combine 2 shares:
# var comb = secrets.combine(shares.slice(1, 3))
#
# //convert back to UTF string:
# comb = secrets.hex2str(comb)
# console.log(comb === pw) // => false
#
# // combine 3 shares:
# comb = secrets.combine([shares[1], shares[3], shares[4]])
#
# //convert back to UTF string:
# comb = secrets.hex2str(comb)
# console.log(comb === pw) // => true
```

## Install it from PyPI

Expand Down
38 changes: 38 additions & 0 deletions gems/example1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# vim: set et sw=4 fenc=utf-8:
#
# example1.py

import json
import js2pysecrets

# // generate a 512-bit key
# key = js2pysecrets.random(512) // => key is a hex string
key = js2pysecrets.random(512)
print(key)

# // split into 10 shares with a threshold of 5
# shares = js2pysecrets.share(key, 10, 5)
# // => shares = ['801xxx...xxx','802xxx...xxx','803xxx...xxx','804xxx...xxx','805xxx...xxx']
shares = js2pysecrets.share(key, 10, 5)
print(shares)

# // combine 4 shares
# var comb = secrets.combine(shares.slice(0, 4))
# console.log(comb === key) // => false
#
# // combine 5 shares
# comb = secrets.combine(shares.slice(4, 9))
# console.log(comb === key) // => true
#
# // combine ALL shares
# comb = secrets.combine(shares)
# console.log(comb === key) // => true
#
# // create another share with id 8
# var newShare = secrets.newShare(8, shares) // => newShare = '808xxx...xxx'
#
# // reconstruct using 4 original shares and the new share:
# comb = secrets.combine(shares.slice(1, 5).concat(newShare))
# console.log(comb === key) // => true
36 changes: 36 additions & 0 deletions gems/example2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# vim: set et sw=4 fenc=utf-8:
#
# example1.py

import json
import js2pysecrets

# var pw = "<<PassWord123>>"
pw = "<<PassWord123>>"

# // convert the text into a hex string
# var pwHex = secrets.str2hex(pw) // => hex string
jsHex = js2pysecrets.str2hex(pw)
print(jsHex)

pyHex = pw.encode('utf-16-be').hex().lstrip('fe')
print(pyHex)

# // split into 5 shares, with a threshold of 3
# var shares = secrets.share(pwHex, 5, 3)
#
# // combine 2 shares:
# var comb = secrets.combine(shares.slice(1, 3))
#
# //convert back to UTF string:
# comb = secrets.hex2str(comb)
# console.log(comb === pw) // => false
#
# // combine 3 shares:
# comb = secrets.combine([shares[1], shares[3], shares[4]])
#
# //convert back to UTF string:
# comb = secrets.hex2str(comb)
# console.log(comb === pw) // => true
1 change: 1 addition & 0 deletions js2pysecrets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from .base import random
from .base import str2hex
from .base import jsFunction
from .base import combine

#with open("VERSION", "r") as version_file:
# __version__ = version_file.read().strip()
1 change: 1 addition & 0 deletions js2pysecrets/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ def __call__(self, *args, **kwargs):
setRNG = jsFunction('setRNG')
str2hex = jsFunction('str2hex')
hex2str = jsFunction('hex2str')
combine = jsFunction('combine')

0 comments on commit 910380c

Please sign in to comment.