|
6 | 6 |
|
7 | 7 | # About |
8 | 8 |
|
9 | | -`js2pysecrets` is a port of the [`secrets.js-grempe`](https://github.com/grempe/secrets.js) JavaScript package to Python. |
| 9 | +`js2pysecrets` is a port of the [`secrets.js`](https://github.com/grempe/secrets.js) JavaScript package to Python. |
10 | 10 |
|
11 | 11 | This package allows for cross-platform compatible shares, *generated using [Shamir's Secret Sharing](http://en.wikipedia.org/wiki/Shamir's_Secret_Sharing)*, to seamlessly interoperate between JavaScript and Python. |
12 | 12 |
|
@@ -87,210 +87,40 @@ comb = secrets.combine(shares[:2]) |
87 | 87 |
|
88 | 88 | //convert back to UTF string: |
89 | 89 | comb = secrets.hex2str(comb) |
90 | | -print(comb === pw) # => False |
| 90 | +print(comb == pw) # => False |
91 | 91 |
|
92 | 92 | // combine 3 shares: |
93 | 93 | comb = secrets.combine([shares[1], shares[3], shares[4]]) |
94 | 94 |
|
95 | 95 | //convert back to UTF string: |
96 | 96 | comb = secrets.hex2str(comb) |
97 | | -print(comb === pw) # => True |
| 97 | +print(comb == pw) # => True |
98 | 98 | ``` |
99 | 99 |
|
100 | | ---- |
| 100 | +## License |
101 | 101 |
|
102 | | -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/). |
103 | | - |
104 | | -## Status |
105 | | - |
106 | | -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. |
107 | | - |
108 | | -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*. |
109 | | - |
110 | | -Combing of shares is not working *yet*... |
111 | | - |
112 | | -### Requirements |
113 | | - |
114 | | -**`Node`** is **required**. |
115 | | - |
116 | | -To use this project in it's current state **and for testing**, `Node` is required on the system. `Node` is always required for testing. It's used to run the `JavaScript` in the local environment. |
117 | | - |
118 | | -## JavaScript Wrapper |
119 | | - |
120 | | -The `JavaScript` wrapper **is not** intended to allow subsequent commands. It spawns an *indvidual* `subprocess` of `Node` for each function called. |
121 | | - |
122 | | -```python |
123 | | -from js2pysecrets import setRNG, random |
124 | | - |
125 | | -setRNG('testRandom') # Output: True |
126 | | - |
127 | | -# New subprocess defaults to 'nodeCryptoRandomBytes' RNG |
128 | | -random(32) # Output: '24c177c8' |
129 | | -random(32) # Output: '89535434' |
130 | | -random(32) # Output: '306e0c23' |
131 | | -``` |
132 | | - |
133 | | -While the `Javascript` *does* have code to allow subsequent commands, the only **INTENDED** use is to force the use of `testRandom` for testing purposes. This can be accomplished by over-riding the function with the key-word argument `test=True`. |
134 | | - |
135 | | -```python |
136 | | -from js2pysecrets import random |
137 | | - |
138 | | -random(32, test=True) # Output: '075bcd15' |
139 | | -random(32, test=True) # Output: '075bcd15' |
140 | | -random(32, test=True) # Output: '075bcd15' |
141 | | -``` |
142 | | - |
143 | | -Additional commands **could** be added on a *case-by-case* basis, support is included in the wrapper. But the intention of the wrapper is mainly to assist testing of a full `Python` implementation to confirm `100%` compatibility with the `JavaScript` version. |
144 | | - |
145 | | -## Examples |
146 | | - |
147 | | -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: |
148 | | - |
149 | | -**Not everything is working yet...** |
150 | | - |
151 | | -```python |
152 | | -import js2pysecrets |
153 | | - |
154 | | -# generate a 512-bit key |
155 | | -# key = js2pysecrets.random(512) // => key is a hex string |
156 | | -key = js2pysecrets.random(512) |
157 | | -print(key) |
158 | | - |
159 | | -# split into 10 shares with a threshold of 5 |
160 | | -# shares = js2pysecrets.share(key, 10, 5) |
161 | | -# => shares = ['801xxx...xxx','802xxx...xxx','803xxx...xxx','804xxx...xxx','805xxx...xxx'] |
162 | | -shares = js2pysecrets.share(key, 10, 5) |
163 | | -print(shares) |
164 | | - |
165 | | -# // combine 4 shares |
166 | | -# var comb = secrets.combine(shares.slice(0, 4)) |
167 | | -# console.log(comb === key) // => false |
168 | | -# |
169 | | -# // combine 5 shares |
170 | | -# comb = secrets.combine(shares.slice(4, 9)) |
171 | | -# console.log(comb === key) // => true |
172 | | -# |
173 | | -# // combine ALL shares |
174 | | -# comb = secrets.combine(shares) |
175 | | -# console.log(comb === key) // => true |
176 | | -# |
177 | | -# // create another share with id 8 |
178 | | -# var newShare = secrets.newShare(8, shares) // => newShare = '808xxx...xxx' |
179 | | -# |
180 | | -# // reconstruct using 4 original shares and the new share: |
181 | | -# comb = secrets.combine(shares.slice(1, 5).concat(newShare)) |
182 | | -# console.log(comb === key) // => true |
183 | | -``` |
184 | | - |
185 | | -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: |
186 | | - |
187 | | -**Things really start to break here...** |
188 | | -*Big and reversed endianness for the `JS` str2hex* |
189 | | - |
190 | | -```python |
191 | | -import js2pysecrets |
192 | | - |
193 | | -# var pw = "<<PassWord123>>" |
194 | | -pw = "<<PassWord123>>" |
195 | | - |
196 | | -# convert the text into a hex string |
197 | | -# jsHex = secrets.str2hex(pw) // => hex string |
198 | | -jsHex = js2pysecrets.str2hex(pw) |
199 | | -print(jsHex) |
200 | | - |
201 | | -# Notice how the JS uses an unconventional str2hex method |
202 | | -pyHex = pw.encode('utf-16').hex().lstrip('fe') # Stripped off the BOM |
203 | | -print(pyHex) |
204 | | - |
205 | | -# split into 5 shares, with a threshold of 3 |
206 | | -# shares = js2pysecrets.share(jsHex, 5, 3) |
207 | | -shares = js2pysecrets.share(jsHex, 5, 3) |
208 | | -print(shares) |
209 | | - |
210 | | -# // combine 2 shares: |
211 | | -# var comb = secrets.combine(shares.slice(1, 3)) |
212 | | -# |
213 | | -# //convert back to UTF string: |
214 | | -# comb = secrets.hex2str(comb) |
215 | | -# console.log(comb === pw) // => false |
216 | | -# |
217 | | -# // combine 3 shares: |
218 | | -# comb = secrets.combine([shares[1], shares[3], shares[4]]) |
219 | | -# |
220 | | -# //convert back to UTF string: |
221 | | -# comb = secrets.hex2str(comb) |
222 | | -# console.log(comb === pw) // => true |
223 | | -``` |
224 | | - |
225 | | -## Install it from PyPI |
226 | | - |
227 | | -```bash |
228 | | -# not published yet - still in development |
229 | | -# pip install js2pysecrets |
230 | | -``` |
231 | | - |
232 | | -## Usage |
233 | | - |
234 | | -```py |
235 | | -import js2pysecrets |
236 | | - |
237 | | -js2pysecrets.rand(32) |
238 | | -js2pysecrets.share('10AF', 6, 3) |
239 | | -``` |
| 102 | +`js2pysecrets` is released under the MIT License. See the `LICENSE` file. |
240 | 103 |
|
241 | 104 | ## Development and Testing |
242 | 105 |
|
243 | 106 | Read the [CONTRIBUTING.md](CONTRIBUTING.md) file. |
244 | 107 |
|
245 | | - |
246 | | -<!-- DELETE THE LINES ABOVE THIS AND WRITE YOUR PROJECT README BELOW --> |
247 | | ----- |
248 | | -# Python Project Template |
249 | | - |
250 | | -A low dependency and really simple to start project template for Python Projects. |
251 | | - |
252 | | -See also |
253 | | -- [Flask-Project-Template](https://github.com/rochacbruno/flask-project-template/) for a full feature Flask project including database, API, admin interface, etc. |
254 | | -- [FastAPI-Project-Template](https://github.com/rochacbruno/fastapi-project-template/) The base to start an openapi project featuring: SQLModel, Typer, FastAPI, JWT Token Auth, Interactive Shell, Management Commands. |
255 | | - |
256 | | -### HOW TO USE THIS TEMPLATE |
257 | | - |
258 | | -> **DO NOT FORK** this is meant to be used from **[Use this template](https://github.com/rochacbruno/python-project-template/generate)** feature. |
259 | | -
|
260 | | -1. Click on **[Use this template](https://github.com/rochacbruno/python-project-template/generate)** |
261 | | -3. Give a name to your project |
262 | | - (e.g. `my_awesome_project` recommendation is to use all lowercase and underscores separation for repo names.) |
263 | | -3. Wait until the first run of CI finishes |
264 | | - (Github Actions will process the template and commit to your new repo) |
265 | | -4. If you want [codecov](https://about.codecov.io/sign-up/) Reports and Automatic Release to [PyPI](https://pypi.org) |
266 | | - On the new repository `settings->secrets` add your `PYPI_API_TOKEN` and `CODECOV_TOKEN` (get the tokens on respective websites) |
267 | | -4. Read the file [CONTRIBUTING.md](CONTRIBUTING.md) |
268 | | -5. Then clone your new project and happy coding! |
269 | | - |
270 | | -> **NOTE**: **WAIT** until first CI run on github actions before cloning your new project. |
271 | | -
|
272 | | -### What is included on this template? |
273 | | - |
274 | | -- 🖼️ Templates for starting multiple application types: |
275 | | - * **Basic low dependency** Python program (default) [use this template](https://github.com/rochacbruno/python-project-template/generate) |
276 | | - * **Flask** with database, admin interface, restapi and authentication [use this template](https://github.com/rochacbruno/flask-project-template/generate). |
277 | | - **or Run `make init` after cloning to generate a new project based on a template.** |
278 | | -- 📦 A basic [setup.py](setup.py) file to provide installation, packaging and distribution for your project. |
279 | | - Template uses setuptools because it's the de-facto standard for Python packages, you can run `make switch-to-poetry` later if you want. |
280 | | -- 🤖 A [Makefile](Makefile) with the most useful commands to install, test, lint, format and release your project. |
281 | | -- 📃 Documentation structure using [mkdocs](http://www.mkdocs.org) |
282 | | -- 💬 Auto generation of change log using **gitchangelog** to keep a HISTORY.md file automatically based on your commit history on every release. |
283 | | -- 🐋 A simple [Containerfile](Containerfile) to build a container image for your project. |
284 | | - `Containerfile` is a more open standard for building container images than Dockerfile, you can use buildah or docker with this file. |
285 | | -- 🧪 Testing structure using [pytest](https://docs.pytest.org/en/latest/) |
286 | | -- ✅ Code linting using [flake8](https://flake8.pycqa.org/en/latest/) |
287 | | -- 📊 Code coverage reports using [codecov](https://about.codecov.io/sign-up/) |
288 | | -- 🛳️ Automatic release to [PyPI](https://pypi.org) using [twine](https://twine.readthedocs.io/en/latest/) and github actions. |
289 | | -- 🎯 Entry points to execute your program using `python -m <js2pysecrets>` or `$ js2pysecrets` with basic CLI argument parsing. |
290 | | -- 🔄 Continuous integration using [Github Actions](.github/workflows/) with jobs to lint, test and release your project on Linux, Mac and Windows environments. |
291 | | - |
292 | | -> Curious about architectural decisions on this template? read [ABOUT_THIS_TEMPLATE.md](ABOUT_THIS_TEMPLATE.md) |
293 | | -> If you want to contribute to this template please open an [issue](https://github.com/rochacbruno/python-project-template/issues) or fork and send a PULL REQUEST. |
294 | | -
|
295 | | -[❤️ Sponsor this project](https://github.com/sponsors/rochacbruno/) |
296 | | - |
| 108 | +## To Do |
| 109 | + |
| 110 | +- Restructure and split into seterate modules |
| 111 | + - Move the backend functions outside the main module |
| 112 | +- Restructure and clean-up the tests |
| 113 | + |
| 114 | +## Changelog |
| 115 | + |
| 116 | +- 0.0.x |
| 117 | + - Documentation, documentation, documentation... |
| 118 | + - Configured automatic release to PyPI |
| 119 | + - Converted `secrets.js` to Python |
| 120 | + - Disabled the `tests_win` GitHub action, #24 |
| 121 | + - Moved docs to use [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) |
| 122 | + - Converted `secrets.js` Jasmine tests to `pytest` versions |
| 123 | + - Added package.json as a stub |
| 124 | + - Built Node.js wrapper for testing |
| 125 | + - Enable CodeCov |
| 126 | + - Started with the [Python Project Template](https://github.com/rochacbruno/python-project-template) |
0 commit comments