Skip to content

Commit 58efeb1

Browse files
authored
Merge pull request #21 from poing/0.0.6
New wrapper using the node_modules approach
2 parents 4ed99a3 + 339ad30 commit 58efeb1

12 files changed

Lines changed: 622 additions & 19 deletions

File tree

gems/test_import2.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
# test.py
66

77
import json
8-
import js2pysecrets
8+
from js2pysecrets import share, combine
9+
import js2pysecrets.node as node
10+
911

1012
# from js2pysecrets import wrapper
1113
#
@@ -24,13 +26,15 @@
2426
# print(js2pysecrets.str2hex(data))
2527
#random = js2pysecrets.jsFunction('random', test=True)
2628
#print(random(32))
27-
print(js2pysecrets.random(32))
28-
print(js2pysecrets.share("ababab", 6, 3, test=True))
29+
print(node.random(32))
30+
print(share("ababab", 6, 3, test=True))
2931

30-
shares = js2pysecrets.share("ababab", 6, 3)
32+
shares = node.share("ababab", 6, 3)
3133
print(shares[1])
3234
print(shares[3])
3335
print(shares[5])
3436

35-
recoveredPass = js2pysecrets.combine([shares[1],shares[3],shares[5]])
36-
print("recovered password is: ", recoveredPass)
37+
recoveredPass = combine([shares[1],shares[3],shares[5]])
38+
print("recovered password is: ", recoveredPass)
39+
40+
node.random(0)

gems/wrapperV12.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// wrapperV11.js
2+
3+
/*
4+
This is the third working version of the wrapper. Better error handling and accepting multiple JavaScript commands for the secrets.js package.
5+
*/
6+
7+
// Hex to ASCII
8+
function hex2a(hex)
9+
{
10+
var str = '';
11+
for (var i = 0; i < hex.length; i += 2)
12+
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
13+
return str;
14+
}
15+
16+
// Require the secrets package and assign it to a variable
17+
const secrets = require('../node_modules/secrets.js-grempe/secrets.js');
18+
19+
// If the script is executed directly, call the appropriate function based on arguments
20+
if (require.main === module) {
21+
const commands = hex2a(process.argv[2]);
22+
23+
if (!commands.length) {
24+
console.error("No commands provided.");
25+
process.exit(1);
26+
}
27+
28+
try {
29+
30+
31+
//return commands;
32+
const inputData = JSON.parse(commands);
33+
34+
// Debugging statements
35+
//console.log("Commands received from Python:", commands);
36+
//console.log("inputData[0][0]: ", inputData[0][0]); // returns: init(33)
37+
38+
// Loop through commands
39+
for (const command of inputData) {
40+
// Evaluate each command
41+
lastResult = eval('secrets.' + command[0]);
42+
}
43+
44+
// Return the result of the last command
45+
console.log(JSON.stringify(lastResult));
46+
47+
} catch (error) {
48+
console.error("Error executing command:", error.message);
49+
process.exit(1);
50+
}
51+
}

gems/wrapperV12_test.py

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#! /usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
# vim: set et sw=4 fenc=utf-8:
4+
#
5+
# wrapperV11_test.py
6+
7+
import json
8+
import subprocess
9+
10+
# Path to the Node.js wrapper script
11+
JS_FILE_PATH = "wrapperV12.js"
12+
13+
def wrapper(input_data):
14+
"""
15+
Run a JavaScript function using the Node.js wrapper.
16+
17+
Args:
18+
input_data (list): List containing the function calls as strings.
19+
20+
Returns:
21+
The result of the JavaScript function or None if there is an error.
22+
"""
23+
24+
# Enclose input_json in single quotes
25+
js_command = ["node", JS_FILE_PATH, input_data]
26+
27+
try:
28+
# Run the command and capture the output and stderr
29+
result = subprocess.run(js_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True)
30+
31+
# Debugging statement to print stdout and stderr
32+
# print("Input data sent to JavaScript:", input_data)
33+
# print("stdout:", result.stdout)
34+
# print("stderr:", result.stderr)
35+
36+
try:
37+
# Attempt to load the entire stdout as JSON
38+
js_result = json.loads(result.stdout)
39+
#print('json.loads')
40+
41+
# Print stderr if it exists
42+
if result.stderr:
43+
print("JavaScript stderr:", result.stderr)
44+
45+
return js_result
46+
47+
except json.JSONDecodeError as e:
48+
print("Python error decoding JSON:", e)
49+
print("Raw stdout content:", result.stdout)
50+
51+
except subprocess.CalledProcessError as e:
52+
# Print the error from the JavaScript script
53+
js_error = e.stderr.strip() # Use e.stderr instead of result.stderr
54+
print("JavaScript error:", js_error)
55+
return None
56+
57+
'''
58+
Used to pass a "clean" string as an arg to the CLI
59+
'''
60+
def encode_to_base36(data):
61+
base36_string = ""
62+
for key, value in data.items():
63+
base36_string += key + str(value)
64+
return base36_string
65+
66+
class JsFunction:
67+
def __init__(self, func, test=False):
68+
self.func = func
69+
self.test = test
70+
71+
def __call__(self, *args, test=False, **kwargs):
72+
def wrapped_func(*args, **kwargs):
73+
args_str = ', '.join(repr(arg) for arg in args)
74+
#kwargs_str = ', '.join(f'{key}={repr(value)}'
75+
# for key, value in kwargs.items())
76+
#all_args = ', '.join(filter(None, [args_str, kwargs_str]))
77+
78+
return f"{self.func.__name__}({args_str})"
79+
80+
data = []
81+
82+
# DO NOT REMOVE THIS
83+
if test or self.test:
84+
data.append("setRNG('testRandom')")
85+
86+
data.append(wrapped_func(*args, **kwargs) if args else self.func(*args, **kwargs))
87+
return data
88+
89+
def __get__(self, instance, owner):
90+
return self if instance is None else types.MethodType(self, instance)
91+
92+
@JsFunction
93+
def init(*args, **kwargs):
94+
pass
95+
96+
@JsFunction
97+
def setRNG(*args, **kwargs):
98+
pass
99+
100+
@JsFunction
101+
def share(*args, **kwargs):
102+
pass
103+
104+
@JsFunction
105+
def combine(*args, **kwargs):
106+
pass
107+
108+
alpha = init(18)
109+
bravo = setRNG("testRandom")
110+
delta = share('1234abc', 6, 3)
111+
112+
113+
# Combine
114+
tasks = [
115+
bravo,
116+
delta
117+
]
118+
119+
#tasks = {alpha, bravo}
120+
121+
#print("Tasks: ", tasks)
122+
123+
124+
125+
json_data = json.dumps(tasks, indent=None).replace("'", "`")
126+
#print(json_data)
127+
#print(json_data.encode().hex())
128+
data = json_data.encode().hex()
129+
#print(data)
130+
# Call the wrapper function
131+
shares = wrapper(data)
132+
133+
print(shares[1])
134+
print(shares[3])
135+
print(shares[5])
136+
137+
foobar = combine([shares[1], shares[3], shares[5]])
138+
tasks = [ foobar ]
139+
json_data = json.dumps(tasks, indent=None).replace("'", "`")
140+
data = json_data.encode().hex()
141+
print(wrapper(data))
142+
# print(shares)
143+
# #print(js_result)
144+
#
145+
# todo = combine([shares[2], shares[3], shares[4]])
146+
# json_data = json.dumps(todo, indent=None).replace("'", "`")
147+
# data = json_data.encode().hex()
148+
#
149+
# answer = wrapper(data)
150+
151+
152+
#print(answer)

javascript/wrapper.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// wrapper.js
2+
3+
/*
4+
A revised and simplified version of JavaScript the wrapper. Accepts multiple JavaScript commands for the secrets.js package, returning the output of the last command.
5+
*/
6+
7+
// Hex to ASCII
8+
function hex2a(hex)
9+
{
10+
var str = '';
11+
for (var i = 0; i < hex.length; i += 2)
12+
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
13+
return str;
14+
}
15+
16+
// Require the secrets package and assign it to a variable
17+
const secrets = require('../node_modules/secrets.js-grempe/secrets.js');
18+
19+
// If the script is executed directly, call the appropriate function based on arguments
20+
if (require.main === module) {
21+
const commands = hex2a(process.argv[2]);
22+
23+
if (!commands.length) {
24+
console.error("No commands provided.");
25+
process.exit(1);
26+
}
27+
28+
try {
29+
// The the commands to execute
30+
const inputData = JSON.parse(commands);
31+
32+
// Debugging statements
33+
//console.log("Commands received from Python:", commands);
34+
//console.log("inputData[0][0]: ", inputData[0][0]); // returns: init(33)
35+
36+
// Loop through commands
37+
for (const command of inputData) {
38+
// Evaluate each command
39+
lastResult = eval('secrets.' + command);
40+
}
41+
42+
// Return the result of the last command
43+
console.log(JSON.stringify(lastResult));
44+
45+
} catch (error) {
46+
console.error("Error executing command:", error.message);
47+
process.exit(1);
48+
}
49+
}

js2pysecrets/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .base import * # noqa
2+
3+
# import .node # noqa

js2pysecrets/base.py

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,61 @@
1-
"""
2-
turbo_parakeet base module.
1+
# import json
32

4-
This is the principal module of the turbo_parakeet project.
5-
here you put your main classes and objects.
3+
from .decorators import JsFunction, jsNeedless
64

7-
Be creative! do whatever you want!
5+
# from .wrapper import wrapper # Import your wrapper function
86

9-
If you want to replace this with a Flask application run:
7+
NAME = "js2pysecrets"
108

11-
$ make init
129

13-
and then choose `flask` as template.
14-
"""
10+
@JsFunction
11+
def share(*args, **kwargs):
12+
pass # pragma: no cover
1513

16-
# example constant variable
17-
NAME = "js2pysecrets"
14+
15+
@JsFunction
16+
def random(*args, **kwargs):
17+
pass # pragma: no cover
18+
19+
20+
@JsFunction
21+
def combine(*args, **kwargs):
22+
pass # pragma: no cover
23+
24+
25+
@jsNeedless
26+
def init(*args, **kwargs):
27+
pass # pragma: no cover
28+
29+
30+
# # Core Functions from secrets.js
31+
# init = jsFunction('init')
32+
# combine = jsFunction('combine')
33+
# getConfig = jsFunction('getConfig')
34+
# extractShareComponents = jsFunction('extractShareComponents')
35+
# setRNG = jsFunction('setRNG')
36+
# str2hex = jsFunction('str2hex')
37+
# hex2str = jsFunction('hex2str')
38+
# random = jsFunction('random')
39+
# share = jsFunction('share')
40+
# newShare = jsFunction('newShare')
41+
#
42+
# # Test Functions
43+
# _reset = jsNeedless('_reset')
44+
# _isSetRNG = jsFunction('_isSetRNG')
45+
46+
# /* test-code */
47+
# // export private functions so they can be unit tested directly.
48+
# _reset: reset,
49+
# _padLeft: padLeft,
50+
# _hex2bin: hex2bin,
51+
# _bin2hex: bin2hex,
52+
# _hasCryptoGetRandomValues: hasCryptoGetRandomValues,
53+
# _hasCryptoRandomBytes: hasCryptoRandomBytes,
54+
# _getRNG: getRNG,
55+
# _isSetRNG: isSetRNG,
56+
# _splitNumStringToIntArray: splitNumStringToIntArray,
57+
# _horner: horner,
58+
# _lagrange: lagrange,
59+
# _getShares: getShares,
60+
# _constructPublicShareString: constructPublicShareString
61+
# /* end-test-code */

0 commit comments

Comments
 (0)