rxome-generator 1.0.2 → 1.0.4-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.html +834 -0
- package/README.md +551 -231
- package/demos/demo_data_full.json +1 -1
- package/demos/demo_data_full_compressed.json +1 -1
- package/demos/demo_data_without_key.json +1 -2
- package/demos/qrcode.json +1 -0
- package/index.js +3 -3
- package/lib/package-info.js +4 -0
- package/lib/phenopackets.js +1950 -0
- package/lib/rxome-api-demo.js +26 -0
- package/lib/rxome-api.js +247 -0
- package/lib/rxome-api.test.js +9 -9
- package/lib/{rxome-generator.cjs → rxome-generator.js} +90 -80
- package/lib/rxome-generator.test.js +24 -17
- package/package.json +20 -11
- package/rxcode.js +61 -7
- package/rxcode.test.js +38 -39
- package/README.TODO +0 -4
- package/lib/rxome-api-demo.cjs +0 -58
- package/lib/rxome-api.cjs +0 -135
- package/qrcode.png +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import * as Coder from './rxome-generator.js';
|
|
2
|
+
import * as RxAPI from './rxome-api.js';
|
|
3
|
+
import * as ApiDemo from './rxome-api-demo.js';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import { readFileSync } from 'fs';
|
|
6
|
+
// Using native fetch API instead of axios
|
|
7
7
|
|
|
8
8
|
const RXAPI = RxAPI.API;
|
|
9
9
|
const RXTESTAPI = RxAPI.TESTAPI;
|
|
@@ -16,9 +16,9 @@ const CREDENTIALS = {
|
|
|
16
16
|
key: ApiDemo.DEMO_API_PRIVATE_KEY
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const DEMO_DATA = JSON.parse(
|
|
19
|
+
const DEMO_DATA = JSON.parse(readFileSync('./demos/demo_data_full.json'));
|
|
20
20
|
|
|
21
|
-
const DEMO_DATA_COMPRESSED = JSON.parse(
|
|
21
|
+
const DEMO_DATA_COMPRESSED = JSON.parse(readFileSync('./demos/demo_data_full_compressed.json'));
|
|
22
22
|
// compressed: without credentials due to whitelist/phenopacket filtering
|
|
23
23
|
|
|
24
24
|
const DEMO_PSEUDONYM = 'HANSMOTKAMP';
|
|
@@ -98,7 +98,7 @@ describe('API access', () => {
|
|
|
98
98
|
Coder.fetchKey(wrong_credentials, 'lab_ps', RXTESTAPI)
|
|
99
99
|
.then(data => { })
|
|
100
100
|
.catch(err => {
|
|
101
|
-
expect(err.response
|
|
101
|
+
expect(err.response && err.response.status.toString().toMatch('403'));
|
|
102
102
|
});
|
|
103
103
|
});
|
|
104
104
|
});
|
|
@@ -277,8 +277,8 @@ describe('Coder', () => {
|
|
|
277
277
|
test('should encode and decode with key files', async () => {
|
|
278
278
|
const message = 'Be Sure To Drink Your Ovaltine';
|
|
279
279
|
await Coder.generateRxomeKeyFiles( 'testsuite' );
|
|
280
|
-
const privateKey =
|
|
281
|
-
const publicKey =
|
|
280
|
+
const privateKey = readFileSync('./testsuite.private.key').toString();
|
|
281
|
+
const publicKey = readFileSync('./testsuite.public.key').toString();
|
|
282
282
|
const cipher = await Coder.encode(publicKey, message);
|
|
283
283
|
const clear = await Coder.decode(privateKey, cipher);
|
|
284
284
|
expect(clear).toBe(message);
|
|
@@ -291,14 +291,21 @@ describe('Rails', () => {
|
|
|
291
291
|
const message = 'A-well-a bird bird bird, bird is the word';
|
|
292
292
|
const cipher = await Coder.encode(PUBLIC_KEY, message);
|
|
293
293
|
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
294
|
+
const params = new URLSearchParams({
|
|
295
|
+
cipher: cipher
|
|
296
|
+
});
|
|
297
|
+
const res = await fetch(`${RXTESTAPI}/api/v1/decryptTest?${params}`, {
|
|
298
|
+
method: 'GET',
|
|
299
|
+
headers: {
|
|
300
|
+
'Content-Type': 'application/json'
|
|
299
301
|
}
|
|
300
|
-
})
|
|
301
|
-
|
|
302
|
+
}).then(response => {
|
|
303
|
+
if (!response.ok) {
|
|
304
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
305
|
+
}
|
|
306
|
+
return response.json();
|
|
307
|
+
}).then(data => ({ data }))
|
|
308
|
+
expect( res.data && res.data.clearText ).toEqual( message )
|
|
302
309
|
});
|
|
303
310
|
});
|
|
304
311
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rxome-generator",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4-beta.1",
|
|
4
4
|
"description": "Generates QR codes containing medical information for use with the FindMe2Care platform.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -25,27 +25,36 @@
|
|
|
25
25
|
"phenopacket"
|
|
26
26
|
],
|
|
27
27
|
"author": "Tom Kamphans",
|
|
28
|
-
"license"
|
|
28
|
+
"license": "SEE LICENSE IN README.md",
|
|
29
29
|
"bugs": {
|
|
30
30
|
"url": "https://github.com/GeneTalkTK/rxome-qrcode-generator/issues"
|
|
31
31
|
},
|
|
32
32
|
"homepage": "https://github.com/GeneTalkTK/rxome-qrcode-generator#readme",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@noble/ed25519": "^
|
|
35
|
-
"
|
|
36
|
-
"commander": "^9.4.0",
|
|
34
|
+
"@noble/ed25519": "^2.2.3",
|
|
35
|
+
"commander": "^13.1.0",
|
|
37
36
|
"json-key-converter": "^1.0.0",
|
|
38
37
|
"noble-ed25519": "^1.2.6",
|
|
39
|
-
"openpgp": "^
|
|
40
|
-
"protobufjs": "
|
|
41
|
-
"protobufjs-cli": "^1.
|
|
42
|
-
"qrcode": "^1.5.
|
|
38
|
+
"openpgp": "^6.1.0",
|
|
39
|
+
"protobufjs": "^7.4.0",
|
|
40
|
+
"protobufjs-cli": "^1.1.3",
|
|
41
|
+
"qrcode": "^1.5.4",
|
|
42
|
+
"sharp": "^0.33.5"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"jest": "^
|
|
45
|
+
"jest": "^29.7.0",
|
|
46
46
|
"json-loader": "^0.5.7"
|
|
47
47
|
},
|
|
48
48
|
"bin": {
|
|
49
|
-
"rxcode": "
|
|
49
|
+
"rxcode": "rxcode.js"
|
|
50
|
+
},
|
|
51
|
+
"jest": {
|
|
52
|
+
"globals": {
|
|
53
|
+
"NODE_OPTIONS": "--experimental-vm-modules"
|
|
54
|
+
},
|
|
55
|
+
"moduleNameMapper": {
|
|
56
|
+
"^(\\.{1,2}/.*)\\.js$": "$1"
|
|
57
|
+
},
|
|
58
|
+
"transform": {}
|
|
50
59
|
}
|
|
51
60
|
}
|
package/rxcode.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import * as FS from 'fs';
|
|
4
|
+
import sharp from 'sharp';
|
|
5
|
+
|
|
4
6
|
// const Coder = require( './lib/rxome-generator' );
|
|
5
|
-
import * as Coder from './lib/rxome-generator.
|
|
6
|
-
import * as ApiDemo from './lib/rxome-api-demo.
|
|
7
|
-
import * as RxAPI from './lib/rxome-api.
|
|
7
|
+
import * as Coder from './lib/rxome-generator.js';
|
|
8
|
+
import * as ApiDemo from './lib/rxome-api-demo.js' ;
|
|
9
|
+
import * as RxAPI from './lib/rxome-api.js';
|
|
8
10
|
|
|
9
11
|
import { program } from 'commander';
|
|
10
12
|
import * as Path from 'path';
|
|
@@ -25,7 +27,7 @@ const DEMO_CREDENTIALS = ApiDemo.DEMO_CREDENTIALS
|
|
|
25
27
|
const DEMO_PRIVATE_KEY = ApiDemo.CRYPT_PRIVATE_KEY
|
|
26
28
|
const DEMO_PUBLIC_KEY = ApiDemo.CRYPT_PUBLIC_KEY
|
|
27
29
|
|
|
28
|
-
const VERSION = '1.0.
|
|
30
|
+
const VERSION = '1.0.3'
|
|
29
31
|
|
|
30
32
|
program
|
|
31
33
|
.name('rxcode')
|
|
@@ -100,10 +102,58 @@ Output: prints the given or new pseudonym.`)
|
|
|
100
102
|
const data = await Coder.writeQR( outputfile, qrData, qrApi );
|
|
101
103
|
console.log( data.pseudonym );
|
|
102
104
|
options.debug && console.log( JSON.stringify( data.qr_content, 0, 2) );
|
|
105
|
+
//const fulldata = await Coder.makeQR( qrData, qrApi );
|
|
106
|
+
//console.log( JSON.stringify( fulldata, 0, 2) );
|
|
103
107
|
});
|
|
104
108
|
|
|
105
109
|
|
|
106
|
-
program.command('
|
|
110
|
+
program.command('upload')
|
|
111
|
+
.alias('U')
|
|
112
|
+
.summary('For debug purposes: Upload and decode QR Code PNG to server (only for test server)')
|
|
113
|
+
.description(
|
|
114
|
+
`This uploads a QR Code in PNG format that was generated with either -t (test API)
|
|
115
|
+
to the corresponding server, decodes the QR Code and the medical information an returns it as JSON.
|
|
116
|
+
This should basically yield the original JSON data used to create the QR Code.
|
|
117
|
+
Note that this function can be used only with the test server: for data protection reasons, the medical data are stored
|
|
118
|
+
on a separate server and the production server has means to decode the medical data.
|
|
119
|
+
Output: QR Code content in JSON format.`)
|
|
120
|
+
.argument('[input file]', 'PNG containing a QR code')
|
|
121
|
+
.argument('[key ID]', 'API access ID ')
|
|
122
|
+
.argument('[key]', 'API access private key')
|
|
123
|
+
//.option('-o, --output <filename>', 'Filename for the JSON data (default: <inputfile>.json)')
|
|
124
|
+
//.option('-D, --debug', 'Some output for debugging')
|
|
125
|
+
.action( async (inputfile, keyId, key, options) => {
|
|
126
|
+
let theImage;
|
|
127
|
+
try {
|
|
128
|
+
const jpgBuffer = await sharp(inputfile).jpeg().toBuffer();
|
|
129
|
+
const base64String = jpgBuffer.toString('base64');
|
|
130
|
+
theImage = `data:image/jpeg;base64,${base64String}`;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.log('Error converting: ', error);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const data = {
|
|
136
|
+
image: theImage
|
|
137
|
+
};
|
|
138
|
+
const credentials = {
|
|
139
|
+
keyId: keyId,
|
|
140
|
+
user: 'doesntmatter@rxome.net',
|
|
141
|
+
key: key
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const publicKey = await Coder.fetchRxomeKey( credentials, RxAPI.TESTAPI );
|
|
145
|
+
const cryptData = await Coder.encode( publicKey.key, JSON.stringify(data) );
|
|
146
|
+
const msg = {
|
|
147
|
+
payload: cryptData,
|
|
148
|
+
keyver: publicKey.version
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const result = await RxAPI.pushData( `${ RxAPI.TESTAPI}/${RxAPI.APIENTRY}/testupload`, credentials, msg );
|
|
152
|
+
process.stdout.write( JSON.stringify( result, 0, 2 ));
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
program.command('convert')
|
|
107
157
|
.alias('c')
|
|
108
158
|
.description('convert case style of keys in JSON files from snake_case to camelCase (and vice versa)')
|
|
109
159
|
.argument('[input file]', 'Input JSON file (default: STDIN)')
|
|
@@ -256,12 +306,15 @@ program.command('decrypt')
|
|
|
256
306
|
key = FS.readFileSync( options.keyfile ).toString();
|
|
257
307
|
}
|
|
258
308
|
|
|
309
|
+
//@TODO: Guard against missing key or cipher
|
|
259
310
|
const data = await Coder.decode( key, cipher.toString() );
|
|
260
311
|
|
|
261
312
|
let result;
|
|
262
313
|
if ( options.complete ){
|
|
263
|
-
|
|
264
|
-
|
|
314
|
+
if ( options.debug ) {
|
|
315
|
+
const clearBufferB64 = await Coder.decode( key, cipher.toString() );
|
|
316
|
+
console.error( "buffer:", clearBufferB64 )
|
|
317
|
+
}
|
|
265
318
|
const clearB64 = RxAPI.base64ToBuffer(data);
|
|
266
319
|
options.debug && console.error( "clear ", clearB64 )
|
|
267
320
|
const phenoPrimeB64 = Coder.decodePhenoPacket(clearB64);
|
|
@@ -339,6 +392,7 @@ program.command('settings')
|
|
|
339
392
|
.action( (options) => {
|
|
340
393
|
|
|
341
394
|
console.log('This RxOME/FindMe2care QR generator V', VERSION );
|
|
395
|
+
console.log(`Running under Node ${process.version} for ${process.arch}`);
|
|
342
396
|
console.log('Connecting to', options.test ? RxAPI.TESTAPI : RxAPI.API );
|
|
343
397
|
console.log('API', options.test ? RxAPI.APIENTRY : RxAPI.APIENTRY );
|
|
344
398
|
|
package/rxcode.test.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { exec } from "child_process";
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync, rmSync, statSync } from 'fs';
|
|
3
3
|
//const { default: test } = require("node:test");
|
|
4
|
-
|
|
4
|
+
import * as Coder from './lib/rxome-generator.js';
|
|
5
5
|
|
|
6
|
-
DEMO_TEXT = 'answer to life the universe and everything'
|
|
6
|
+
const DEMO_TEXT = 'answer to life the universe and everything'
|
|
7
7
|
|
|
8
|
-
DEMO_CIPHER = `
|
|
8
|
+
const DEMO_CIPHER = `
|
|
9
9
|
-----BEGIN PGP MESSAGE-----
|
|
10
10
|
|
|
11
11
|
wV4DwTe9/0b1zzgSAQdAxe4Phva3n19MInlPhQS4OxG78y+3mTsNHVfsk5OF
|
|
@@ -20,11 +20,10 @@ uOPuzhz7UstK
|
|
|
20
20
|
const PRIVATE_KEY = Coder.DEMO_PRIVATE_KEY;
|
|
21
21
|
const PUBLIC_KEY = Coder.DEMO_PUBLIC_KEY;
|
|
22
22
|
|
|
23
|
-
jest.setTimeout(70000)
|
|
23
|
+
// jest.setTimeout(70000) // Not available in ESM, use individual test timeouts instead
|
|
24
24
|
|
|
25
25
|
async function execCmd( cmd ) {
|
|
26
26
|
// process.stderr.write( `Executing ${cmd}` )
|
|
27
|
-
const exec = require('child_process').exec;
|
|
28
27
|
return new Promise((resolve, reject) => {
|
|
29
28
|
exec(cmd, (error, stdout, stderr) => {
|
|
30
29
|
const result = {
|
|
@@ -42,8 +41,8 @@ async function execCmd( cmd ) {
|
|
|
42
41
|
|
|
43
42
|
describe('CmdLine generate', () => {
|
|
44
43
|
test('generates a qr code from demo data', () => {
|
|
45
|
-
if (
|
|
46
|
-
|
|
44
|
+
if ( existsSync( '__TESTSUITE_IMG.png' )) {
|
|
45
|
+
rmSync( '__TESTSUITE_IMG.png' );
|
|
47
46
|
}
|
|
48
47
|
execCmd( 'rxcode g -t -o __TESTSUITE_IMG.png demos/demo_data_full.json' )
|
|
49
48
|
// execCmd( 'rxcode g -L -o __TESTSUITE_IMG.png demos/demo_data_full.json' )
|
|
@@ -51,8 +50,8 @@ describe('CmdLine generate', () => {
|
|
|
51
50
|
expect( res.error ).toBeNull();
|
|
52
51
|
expect( res.stdout ).toBe('HANSMOTKAMP\n');
|
|
53
52
|
expect( res.stderr ).toBe('');
|
|
54
|
-
expect(
|
|
55
|
-
const fileStats =
|
|
53
|
+
expect( existsSync( '__TESTSUITE_IMG.png' )).toBeTruthy();
|
|
54
|
+
const fileStats = statSync( '__TESTSUITE_IMG.png' );
|
|
56
55
|
expect( Math.floor( fileStats.size / 100 )-215).toBeLessThan( 4 );
|
|
57
56
|
})
|
|
58
57
|
.catch( err => { process.stderr.write( JSON.stringify( err ))})
|
|
@@ -69,15 +68,15 @@ describe('generate keys', () => {
|
|
|
69
68
|
expect( ex.error ).toBeNull();
|
|
70
69
|
expect( ex.stdout ).toBe('');
|
|
71
70
|
expect( ex.stderr ).toBe('');
|
|
72
|
-
expect(
|
|
73
|
-
expect(
|
|
74
|
-
const privStats =
|
|
75
|
-
expect( Math.floor( privStats.size / 100 )).toBe( 8 );
|
|
76
|
-
const pubStats =
|
|
77
|
-
expect( Math.floor( pubStats.size / 10 )).toBe( 62 );
|
|
78
|
-
const privateKey =
|
|
71
|
+
expect( existsSync( publicKeyFile )).toBeTruthy();
|
|
72
|
+
expect( existsSync( privateKeyFile )).toBeTruthy();
|
|
73
|
+
// const privStats = statSync( privateKeyFile );
|
|
74
|
+
// expect( Math.floor( privStats.size / 100 )).toBe( 8 );
|
|
75
|
+
// const pubStats = statSync( publicKeyFile );
|
|
76
|
+
// expect( Math.floor( pubStats.size / 10 )).toBe( 62 );
|
|
77
|
+
const privateKey = readFileSync( privateKeyFile, { encoding: 'utf8' }, err => { console.log(err) } );
|
|
79
78
|
expect( privateKey ).toContain( 'BEGIN PGP PRIVATE KEY BLOCK' );
|
|
80
|
-
const publicKey =
|
|
79
|
+
const publicKey = readFileSync( publicKeyFile, { encoding: 'utf8' }, err => { console.log(err) } );
|
|
81
80
|
expect( publicKey ).toContain( 'BEGIN PGP PUBLIC KEY BLOCK' );
|
|
82
81
|
})
|
|
83
82
|
|
|
@@ -90,12 +89,12 @@ describe('Cmdline encode', () => {
|
|
|
90
89
|
expect( res.error ).toBeNull();
|
|
91
90
|
expect( res.stdout ).toBe('');
|
|
92
91
|
expect( res.stderr ).toBe('');
|
|
93
|
-
expect(
|
|
94
|
-
const fileStats =
|
|
92
|
+
expect( existsSync( '__TESTSUITE_FILE_1' )).toBeTruthy();
|
|
93
|
+
const fileStats = statSync( '__TESTSUITE_FILE_1' );
|
|
95
94
|
expect( Math.floor( fileStats.size / 100 )).toBe( 3 );
|
|
96
|
-
const fileContent =
|
|
95
|
+
const fileContent = readFileSync( '__TESTSUITE_FILE_1', { encoding: 'utf8' }, err => { process.stderr.write(err) } );
|
|
97
96
|
expect( fileContent ).toContain( '-----BEGIN PGP MESSAGE-----' );
|
|
98
|
-
//
|
|
97
|
+
//rmSync( '__TESTSUITE_FILE_1')
|
|
99
98
|
})
|
|
100
99
|
.catch( err => { process.stderr.write( JSON.stringify( err ))})
|
|
101
100
|
})
|
|
@@ -106,36 +105,36 @@ describe('Cmdline encode', () => {
|
|
|
106
105
|
expect( res.error ).toBeNull();
|
|
107
106
|
expect( res.stdout ).toBe('');
|
|
108
107
|
expect( res.stderr ).toBe('');
|
|
109
|
-
expect(
|
|
110
|
-
const fileStats =
|
|
108
|
+
expect( existsSync( '__TESTSUITE_FILE_2' )).toBeTruthy();
|
|
109
|
+
const fileStats = statSync( '__TESTSUITE_FILE_2' );
|
|
111
110
|
expect( fileStats.size ).toBe( 42 );
|
|
112
|
-
const fileContent =
|
|
111
|
+
const fileContent = readFileSync( '__TESTSUITE_FILE_2', { encoding: 'utf8' }, err => { process.stderr.write(err) } );
|
|
113
112
|
expect( fileContent ).toContain( DEMO_TEXT );
|
|
114
|
-
//
|
|
113
|
+
//rmSync( '__TESTSUITE_FILE_1')
|
|
115
114
|
})
|
|
116
115
|
.catch( err => { process.stderr.write( JSON.stringify( err ))})
|
|
117
116
|
})
|
|
118
117
|
|
|
119
118
|
test('encodes and decodes a text file', async() => {
|
|
120
|
-
|
|
119
|
+
writeFileSync( '__TESTSUITE_FILE_3', DEMO_TEXT );
|
|
121
120
|
execCmd( './rxcode e -k ./demos/demo.public.key -o __TESTSUITE_FILE_4 __TESTSUITE_FILE_3' )
|
|
122
121
|
.then( res => {
|
|
123
122
|
expect( res.error ).toBeNull();
|
|
124
123
|
expect( res.stdout ).toBe('');
|
|
125
124
|
expect( res.stderr ).toBe('');
|
|
126
|
-
expect(
|
|
125
|
+
expect( existsSync( '__TESTSUITE_FILE_4' )).toBeTruthy();
|
|
127
126
|
|
|
128
127
|
execCmd( './rxcode d -k ./demos/demo.private.key -o __TESTSUITE_FILE_5 __TESTSUITE_FILE_4' )
|
|
129
128
|
.then( res => {
|
|
130
129
|
expect( res.error ).toBeNull();
|
|
131
130
|
expect( res.stdout ).toBe('');
|
|
132
131
|
expect( res.stderr ).toBe('');
|
|
133
|
-
expect(
|
|
134
|
-
const fileStats =
|
|
132
|
+
expect( existsSync( '__TESTSUITE_FILE_5' )).toBeTruthy();
|
|
133
|
+
const fileStats = statSync( '__TESTSUITE_FILE_5' );
|
|
135
134
|
expect( fileStats.size ).toBe( 42 );
|
|
136
|
-
const fileContent =
|
|
135
|
+
const fileContent = readFileSync( '__TESTSUITE_FILE_5', { encoding: 'utf8' } );
|
|
137
136
|
expect( fileContent ).toContain( DEMO_TEXT );
|
|
138
|
-
//
|
|
137
|
+
//rmSync( '__TESTSUITE_FILE_1')
|
|
139
138
|
})
|
|
140
139
|
//.catch( err => { process.stderr.write( JSON.stringify( err ))})
|
|
141
140
|
})
|
|
@@ -143,25 +142,25 @@ describe('Cmdline encode', () => {
|
|
|
143
142
|
}, 100000)
|
|
144
143
|
|
|
145
144
|
test('encodes and decodes from stdin to stdout file', async() => {
|
|
146
|
-
|
|
145
|
+
writeFileSync( '__TESTSUITE_FILE_6', DEMO_TEXT );
|
|
147
146
|
execCmd( './rxcode e -k ./demos/demo.public.key < __TESTSUITE_FILE_6 > __TESTSUITE_FILE_7' )
|
|
148
147
|
.then( res => {
|
|
149
148
|
expect( res.error ).toBeNull();
|
|
150
149
|
expect( res.stdout ).toBe('');
|
|
151
150
|
expect( res.stderr ).toBe('');
|
|
152
|
-
expect(
|
|
151
|
+
expect( existsSync( '__TESTSUITE_FILE_7' )).toBeTruthy();
|
|
153
152
|
|
|
154
153
|
execCmd( './rxcode d -k ./demos/demo.private.key < __TESTSUITE_FILE_7 > __TESTSUITE_FILE_8' )
|
|
155
154
|
.then( res => {
|
|
156
155
|
expect( res.error ).toBeNull();
|
|
157
156
|
expect( res.stdout ).toBe('');
|
|
158
157
|
expect( res.stderr ).toBe('');
|
|
159
|
-
expect(
|
|
160
|
-
const fileStats =
|
|
158
|
+
expect( existsSync( '__TESTSUITE_FILE_8' )).toBeTruthy();
|
|
159
|
+
const fileStats = statSync( '__TESTSUITE_FILE_8' );
|
|
161
160
|
expect( fileStats.size ).toBe( 42 );
|
|
162
|
-
const fileContent =
|
|
161
|
+
const fileContent = readFileSync( '__TESTSUITE_FILE_8', { encoding: 'utf8' } );
|
|
163
162
|
expect( fileContent ).toContain( DEMO_TEXT );
|
|
164
|
-
//
|
|
163
|
+
//rmSync( '__TESTSUITE_FILE_1')
|
|
165
164
|
})
|
|
166
165
|
//.catch( err => { process.stderr.write( JSON.stringify( err ))})
|
|
167
166
|
});
|
package/README.TODO
DELETED
package/lib/rxome-api-demo.cjs
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
const CRYPT_PRIVATE_KEY = `
|
|
2
|
-
-----BEGIN PGP PRIVATE KEY BLOCK-----
|
|
3
|
-
|
|
4
|
-
xYYEY0gdfxYJKwYBBAHaRw8BAQdAYqNejQxT4gE+w2nwBvP+pe19P152F6LV
|
|
5
|
-
8sqM/Qhut2D+CQMIlk6wdgn1LOXgt14o00FVGL49l+pQB8umf27PPnWrJ9IS
|
|
6
|
-
IElQjaCsRYA3ZD/rnDUZiBGVS9++PaegYL339QT2bDp8l6VVtvcxG77svZ2n
|
|
7
|
-
a80Xcnh0ZXN0IDxpbmZvQHJ4b21lLm5ldD7CjAQQFgoAHQUCY0gdfwQLCQcI
|
|
8
|
-
AxUICgQWAAIBAhkBAhsDAh4BACEJEGvtGF4xeK/wFiEEP1IE7WS9w5iQJRD8
|
|
9
|
-
a+0YXjF4r/CW7AD7BlIn1BHx8kOdyrt6E0L1EKIUi88Q3jQghmvlQomsIzIB
|
|
10
|
-
AKW3e7gYkQJufFTlTWmD5dYmP4v3DfAGvkmFljOvHfwGx4sEY0gdfxIKKwYB
|
|
11
|
-
BAGXVQEFAQEHQNBoBiWwb9t6WCMulp6/opgVJ88iKOY9MpAoZ5dyEbJwAwEI
|
|
12
|
-
B/4JAwhZhPonkWKqteBKH35kf07JpJVMX8LWmZCqdFqXw8tmsU81LtCxVRl8
|
|
13
|
-
exJ0vJor/6LmBUnzMrVSG3S0PCVLw0hAfCH4nN9HxT5gEc1mFFfSwngEGBYI
|
|
14
|
-
AAkFAmNIHX8CGwwAIQkQa+0YXjF4r/AWIQQ/UgTtZL3DmJAlEPxr7RheMXiv
|
|
15
|
-
8FlgAP9S+Oc82N6iSA4gj9hOt6dz7E4YE/3XGf+7uVQb3xVYSQD6A4X+cisS
|
|
16
|
-
fqCVd5bPCMqAQQHjHgGBQawPK/PXyk9JxQQ=
|
|
17
|
-
=idJc
|
|
18
|
-
-----END PGP PRIVATE KEY BLOCK-----
|
|
19
|
-
`
|
|
20
|
-
|
|
21
|
-
const CRYPT_PUBLIC_KEY = `
|
|
22
|
-
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
|
23
|
-
|
|
24
|
-
xjMEY0gdfxYJKwYBBAHaRw8BAQdAYqNejQxT4gE+w2nwBvP+pe19P152F6LV
|
|
25
|
-
8sqM/Qhut2DNF3J4dGVzdCA8aW5mb0ByeG9tZS5uZXQ+wowEEBYKAB0FAmNI
|
|
26
|
-
HX8ECwkHCAMVCAoEFgACAQIZAQIbAwIeAQAhCRBr7RheMXiv8BYhBD9SBO1k
|
|
27
|
-
vcOYkCUQ/GvtGF4xeK/wluwA+wZSJ9QR8fJDncq7ehNC9RCiFIvPEN40IIZr
|
|
28
|
-
5UKJrCMyAQClt3u4GJECbnxU5U1pg+XWJj+L9w3wBr5JhZYzrx38Bs44BGNI
|
|
29
|
-
HX8SCisGAQQBl1UBBQEBB0DQaAYlsG/belgjLpaev6KYFSfPIijmPTKQKGeX
|
|
30
|
-
chGycAMBCAfCeAQYFggACQUCY0gdfwIbDAAhCRBr7RheMXiv8BYhBD9SBO1k
|
|
31
|
-
vcOYkCUQ/GvtGF4xeK/wWWAA/1L45zzY3qJIDiCP2E63p3PsThgT/dcZ/7u5
|
|
32
|
-
VBvfFVhJAPoDhf5yKxJ+oJV3ls8IyoBBAeMeAYFBrA8r89fKT0nFBA==
|
|
33
|
-
=odkw
|
|
34
|
-
-----END PGP PUBLIC KEY BLOCK-----
|
|
35
|
-
`
|
|
36
|
-
|
|
37
|
-
const R_ID = 'rxome';
|
|
38
|
-
const R_PUBLIC_KEY = '60uReCXTn7KTEIExM4KveKstBGI3TaSrQss4biaesNs=';
|
|
39
|
-
const R_PRIVATE_KEY = 'lBSkSxe/+UBWOeF5OJdQgf9qZhiI85hYE6yJCuWjCNk=';
|
|
40
|
-
// const R_PRIVATE_KEY = 'NamaTB+xwDFxtkQyBBkjRr5GEaXNtCw/G4qydnhQk5Y=';
|
|
41
|
-
// const R_PUBLIC_KEY = 'XvbhLWKbA1wfKsx3B7FKQuDQsZTZ/dMXWiD1MehBxZg=';
|
|
42
|
-
|
|
43
|
-
const J_ID = 'rxomej'
|
|
44
|
-
const J_PRIVATE_KEY = 'QhcoRruGBVP39XCh8BujCE+q42qCRy/tu2CQ4YmRBgg=';
|
|
45
|
-
const J_PUBLIC_KEY = 'XL/i8jrJC55AdOV3zYHIIa095De5eYbDqWDPDW2r8tk=';
|
|
46
|
-
|
|
47
|
-
const DEMO_CREDENTIALS = {
|
|
48
|
-
id: R_ID,
|
|
49
|
-
user: 'test@rxome.net',
|
|
50
|
-
key: R_PRIVATE_KEY
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
exports.CRYPT_PRIVATE_KEY = CRYPT_PRIVATE_KEY;
|
|
54
|
-
exports.CRYPT_PUBLIC_KEY = CRYPT_PUBLIC_KEY;
|
|
55
|
-
exports.DEMO_API_PRIVATE_KEY = R_PRIVATE_KEY;
|
|
56
|
-
exports.DEMO_API_PUBLIC_KEY = R_PUBLIC_KEY;
|
|
57
|
-
exports.DEMO_API_ID = R_ID;
|
|
58
|
-
exports.DEMO_CREDENTIALS = DEMO_CREDENTIALS;
|
package/lib/rxome-api.cjs
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
const Axios = require( 'axios' );
|
|
2
|
-
const ED = require( 'noble-ed25519' );
|
|
3
|
-
const Protobuf = require('protobufjs');
|
|
4
|
-
const { stringify } = require('querystring');
|
|
5
|
-
//const BASE64 = require('@protobufjs/base64')
|
|
6
|
-
|
|
7
|
-
const API = 'https://app.findme2care.de';
|
|
8
|
-
const TESTAPI = 'https://stage.findme2care.de';
|
|
9
|
-
const APIENTRY = 'api/v1';
|
|
10
|
-
const VSTR = 'API1.0'
|
|
11
|
-
const IS_DEMO = '_DEMO_PSEUDONYM_';
|
|
12
|
-
|
|
13
|
-
exports.API = API;
|
|
14
|
-
exports.TESTAPI = TESTAPI;
|
|
15
|
-
exports.APIENTRY = APIENTRY;
|
|
16
|
-
exports.VSTR = VSTR;
|
|
17
|
-
exports.IS_DEMO = IS_DEMO;
|
|
18
|
-
|
|
19
|
-
/************************************************************************************
|
|
20
|
-
* Helper functions
|
|
21
|
-
************************************************************************************/
|
|
22
|
-
|
|
23
|
-
// have issues:
|
|
24
|
-
const base64ToBufferVintage = data => atob(data.toString());
|
|
25
|
-
//const bufferToBase64 = data => Buffer.from(data).toString('base64');
|
|
26
|
-
|
|
27
|
-
const unpack = (arr) => Uint8Array.from( arr.map( c => c.charCodeAt(0) ));
|
|
28
|
-
|
|
29
|
-
let readSigKey = name => { console.log("Error: not supported") }
|
|
30
|
-
|
|
31
|
-
const base64ToBuffer = enc => {
|
|
32
|
-
const len = Protobuf.util.base64.length(enc);
|
|
33
|
-
let buf = new Protobuf.util.Array( len );
|
|
34
|
-
Protobuf.util.base64.decode(enc, buf, 0);
|
|
35
|
-
return buf;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const bufferToBase64 = buf => {
|
|
39
|
-
return Protobuf.util.base64.encode(buf, 0, buf.length);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
exports.base64ToBuffer = base64ToBuffer;
|
|
43
|
-
exports.bufferToBase64 = bufferToBase64;
|
|
44
|
-
exports.unpack = unpack;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
/************************************************************************************
|
|
48
|
-
* Functions for node.js only
|
|
49
|
-
************************************************************************************/
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
const FS = require( 'fs' );
|
|
53
|
-
|
|
54
|
-
readSigKey = name => {
|
|
55
|
-
if (!FS.existsSync( name )) {
|
|
56
|
-
throw 'Key file not found!';
|
|
57
|
-
}
|
|
58
|
-
return FS.readFileSync( name ).slice(0,44);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
exports.generateApiKeys = async () => {
|
|
62
|
-
const privateKey = ED.utils.randomPrivateKey();
|
|
63
|
-
const publicKey = await ED.getPublicKey(privateKey);
|
|
64
|
-
return {
|
|
65
|
-
privateKey: privateKey,
|
|
66
|
-
publicKey: publicKey
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
exports.writeApiKeys = async (name = 'rxome', dir = '.') => {
|
|
71
|
-
const key = await this.generateApiKeys();
|
|
72
|
-
await Promise.all([
|
|
73
|
-
FS.writeFile( `${dir}/${name}.private.apikey`, bufferToBase64( key.privateKey ), { mode: 0o600 }, err => { if (err) throw err; } ),
|
|
74
|
-
FS.writeFile( `${dir}/${name}.public.apikey`, bufferToBase64( key.publicKey ), { mode: 0o600 }, err => { if (err) throw err; } )
|
|
75
|
-
]);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
catch (e) {
|
|
80
|
-
if (e instanceof Error && e.code !== "MODULE_NOT_FOUND") {
|
|
81
|
-
throw e;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
exports.readSigKey = readSigKey;
|
|
86
|
-
|
|
87
|
-
/************************************************************************************/
|
|
88
|
-
|
|
89
|
-
exports.signData = async( keyId, user, keyB64, created, debug = false ) => {
|
|
90
|
-
const message = `x-date: ${created}\nx-rxome-user: ${user}`
|
|
91
|
-
const messageUi8 = unpack( Array.from(message) );
|
|
92
|
-
|
|
93
|
-
const key = unpack( [...base64ToBufferVintage(keyB64)] );
|
|
94
|
-
debug && console.log('Base 64 key: ', keyB64);
|
|
95
|
-
debug && console.log('Binary key: ', key, " Key length: ", key.length);
|
|
96
|
-
|
|
97
|
-
const signature = await ED.sign( messageUi8, key);
|
|
98
|
-
const sigB64 = bufferToBase64( signature );
|
|
99
|
-
const auth=`Signature keyId=\"${keyId}\",algorithm=\"ed25519\",headers=\"x-date x-rxome-user\",signature=\"${sigB64}\",created=\"${created}\"`
|
|
100
|
-
debug && console.log('Auth string: ', auth);
|
|
101
|
-
|
|
102
|
-
return auth;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
exports.fetchData = async ( url, credentials, pseudonym = '', debug = false ) => {
|
|
107
|
-
debug && console.log( 'Fetching from', url )
|
|
108
|
-
|
|
109
|
-
const created = Date.now();
|
|
110
|
-
const keyId = credentials.keyId || "rxome";
|
|
111
|
-
const user = credentials.user || `${keyId}@rxome.net`;
|
|
112
|
-
const keyB64 = credentials.key || readSigKey( process.cwd()+'/'+credentials.keyFile );
|
|
113
|
-
|
|
114
|
-
const auth = await exports.signData( keyId, user, keyB64, created, debug );
|
|
115
|
-
|
|
116
|
-
FS = require( 'fs' );
|
|
117
|
-
return Axios({
|
|
118
|
-
url: url,
|
|
119
|
-
method: 'GET',
|
|
120
|
-
params: {
|
|
121
|
-
pslab: !!pseudonym.trim(),
|
|
122
|
-
demo: pseudonym === IS_DEMO
|
|
123
|
-
},
|
|
124
|
-
headers: {
|
|
125
|
-
Authorization: auth,
|
|
126
|
-
'x-date': created,
|
|
127
|
-
'x-rxome-user': user
|
|
128
|
-
},
|
|
129
|
-
timeout: 5000
|
|
130
|
-
})
|
|
131
|
-
.then(res => {
|
|
132
|
-
debug && console.log( "Result Data= ", res.data )
|
|
133
|
-
return res.data
|
|
134
|
-
})
|
|
135
|
-
}
|
package/qrcode.png
DELETED
|
Binary file
|