rxome-generator 0.1.0

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.
@@ -0,0 +1,56 @@
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_PRIVATE_KEY = 'NamaTB+xwDFxtkQyBBkjRr5GEaXNtCw/G4qydnhQk5Y=';
39
+ const R_PUBLIC_KEY = 'XvbhLWKbA1wfKsx3B7FKQuDQsZTZ/dMXWiD1MehBxZg=';
40
+
41
+ const J_ID = 'rxomej'
42
+ const J_PRIVATE_KEY = 'QhcoRruGBVP39XCh8BujCE+q42qCRy/tu2CQ4YmRBgg=';
43
+ const J_PUBLIC_KEY = 'XL/i8jrJC55AdOV3zYHIIa095De5eYbDqWDPDW2r8tk=';
44
+
45
+ const DEMO_CREDENTIALS = {
46
+ id: R_ID,
47
+ user: 'test@rxome.net',
48
+ key: R_PRIVATE_KEY
49
+ }
50
+
51
+ exports.CRYPT_PRIVATE_KEY = CRYPT_PRIVATE_KEY;
52
+ exports.CRYPT_PUBLIC_KEY = CRYPT_PUBLIC_KEY;
53
+ exports.DEMO_API_PRIVATE_KEY = R_PRIVATE_KEY;
54
+ exports.DEMO_API_PUBLIC_KEY = R_PUBLIC_KEY;
55
+ exports.DEMO_API_ID = R_ID;
56
+ exports.DEMO_CREDENTIALS = DEMO_CREDENTIALS;
@@ -0,0 +1,119 @@
1
+ const Axios = require( 'axios' );
2
+ const ED = require( 'noble-ed25519' );
3
+ const Protobuf = require('protobufjs');
4
+ //const BASE64 = require('@protobufjs/base64')
5
+
6
+ const API = 'https://www.rxome.net';
7
+ const TESTAPI = 'https://testapi.gene-talk.de';
8
+ const APIENTRY = 'api/v1';
9
+ const VSTR = 'API1.0'
10
+ exports.API = API;
11
+ exports.TESTAPI = TESTAPI;
12
+ exports.APIENTRY = APIENTRY;
13
+ exports.VSTR = VSTR;
14
+
15
+ /************************************************************************************
16
+ * Helper functions
17
+ ************************************************************************************/
18
+
19
+ // have issues:
20
+ const base64ToBufferVintage = data => atob(data.toString());
21
+ //const bufferToBase64 = data => Buffer.from(data).toString('base64');
22
+
23
+ const unpack = (arr) => Uint8Array.from( arr.map( c => c.charCodeAt(0) ));
24
+
25
+ let readSigKey = name => { console.log("Error: not supported") }
26
+
27
+ const base64ToBuffer = enc => {
28
+ const len = Protobuf.util.base64.length(enc);
29
+ let buf = new Protobuf.util.Array( len );
30
+ Protobuf.util.base64.decode(enc, buf, 0);
31
+ return buf;
32
+ }
33
+
34
+ const bufferToBase64 = buf => {
35
+ return Protobuf.util.base64.encode(buf, 0, buf.length);
36
+ }
37
+
38
+ exports.base64ToBuffer = base64ToBuffer;
39
+ exports.bufferToBase64 = bufferToBase64;
40
+ exports.unpack = unpack;
41
+
42
+
43
+ /************************************************************************************
44
+ * Functions for node.js only
45
+ ************************************************************************************/
46
+
47
+ try {
48
+ const FS = require( 'fs' );
49
+
50
+ readSigKey = name => {
51
+ if (!FS.existsSync( name )) {
52
+ throw 'Key file not found!';
53
+ }
54
+ return FS.readFileSync( name ).slice(0,44);
55
+ }
56
+
57
+ exports.generateApiKeys = async (name = 'rxome', dir = '.') => {
58
+ const privateKey = ED.utils.randomPrivateKey();
59
+ const publicKey = await ED.getPublicKey(privateKey);
60
+ await Promise.all([
61
+ FS.writeFile( `${dir}/${name}.private.apikey`, bufferToBase64( privateKey ), { mode: 0o600 }, err => { if (err) throw err; } ),
62
+ FS.writeFile( `${dir}/${name}.public.apikey`, bufferToBase64( publicKey ), { mode: 0o600 }, err => { if (err) throw err; } )
63
+ ]);
64
+ }
65
+
66
+ }
67
+ catch (e) {
68
+ if (e instanceof Error && e.code !== "MODULE_NOT_FOUND") {
69
+ throw e;
70
+ }
71
+ }
72
+
73
+ /************************************************************************************/
74
+
75
+ exports.signData = async( keyId, user, keyB64, created, debug = false ) => {
76
+ const message = `x-date: ${created}\nx-rxome-user: ${user}`
77
+ const messageUi8 = unpack( Array.from(message) );
78
+
79
+ const key = unpack( [...base64ToBufferVintage(keyB64)] );
80
+ debug && console.log('Base 64 key: ', keyB64);
81
+ debug && console.log('Binary key: ', key, " Key length: ", key.length);
82
+
83
+ const signature = await ED.sign( messageUi8, key);
84
+ const sigB64 = bufferToBase64( signature );
85
+ const auth=`Signature keyId=\"${keyId}\",algorithm=\"ed25519\",headers=\"x-date x-rxome-user\",signature=\"${sigB64}\",created=\"${created}\"`
86
+ debug && console.log('Auth string: ', auth);
87
+
88
+ return auth;
89
+ }
90
+
91
+
92
+ exports.fetchData = async ( url, credentials, pseudonym = '', debug = false ) => {
93
+ debug && console.log( 'Fetching from', url )
94
+
95
+ const created = Date.now();
96
+ const keyId = credentials.keyId || "rxome";
97
+ const user = credentials.user || `${keyId}@rxome.net`;
98
+ const keyB64 = credentials.key || readSigKey( process.cwd()+'/'+credentials.keyFile );
99
+
100
+ auth = await exports.signData( keyId, user, keyB64, created, debug );
101
+
102
+ return Axios({
103
+ url: url,
104
+ method: 'GET',
105
+ params: {
106
+ pslab: !!pseudonym.trim()
107
+ },
108
+ headers: {
109
+ Authorization: auth,
110
+ 'x-date': created,
111
+ 'x-rxome-user': user
112
+ },
113
+ timeout: 5000
114
+ })
115
+ .then(res => {
116
+ debug && console.log( "Result Data= ", res.data )
117
+ return res.data
118
+ })
119
+ }
@@ -0,0 +1,22 @@
1
+ const RxAPI = require('./rxome-api');
2
+ const FS = require('fs');
3
+ const ED = require( 'noble-ed25519' );
4
+
5
+ describe('API access', () => {
6
+ test.skip('generates valid API access keys', async () => {
7
+ await RxAPI.generateApiKeys( 'jesttest' );
8
+ expect( FS.existsSync('jesttest.private.apikey') ).toBe( true );
9
+ expect( FS.existsSync('jesttest.public.apikey') ).toBe( true );
10
+ expect( FS.statSync('jesttest.private.apikey').size - 44 ).toBeLessThan( 2 );
11
+ expect( FS.statSync('jesttest.public.apikey').size - 44 ).toBeLessThan( 2 );
12
+
13
+ const message='Answer to life the universe and everything';
14
+ const messageUi8 = RxAPI.unpack(Array.from(message));
15
+ const privKey = RxAPI.unpack([...RxAPI.base64ToBuffer( FS.readFileSync('jesttest.private.apikey'))])
16
+ const pubKey = RxAPI.unpack([...RxAPI.base64ToBuffer( FS.readFileSync('jesttest.public.apikey'))])
17
+ const signature = await ED.sign(messageUi8, privKey);
18
+ const isValid = await ED.verify(signature, messageUi8, pubKey);
19
+ expect( isValid ).toBeTruthy;
20
+ });
21
+
22
+ });
@@ -0,0 +1,349 @@
1
+ // https://openpgpjs.org/
2
+ const PGP = require( 'openpgp' );
3
+
4
+ // https://github.com/soldair/node-qrcode
5
+ const QRCode = require( 'qrcode' );
6
+
7
+ const jsonKeyConverter = require('json-key-converter');
8
+ const Protobuf = require('protobufjs');
9
+ const PhenoPacketDescriptor = require("./phenopackets.json");
10
+
11
+ //const { constants } = require('buffer');
12
+
13
+ const RxAPI= require('./rxome-api');
14
+
15
+ const apiVer = '1.0';
16
+ const RXAPI = RxAPI.API;
17
+ const RXTESTAPI = RxAPI.TESTAPI;
18
+ const APIENTRY = RxAPI.APIENTRY;
19
+
20
+ const PASSPHRASE = 'n0thin6r3@11ym@773r5';
21
+
22
+ // const ProtoBufRoot = await Protobuf.load('assets/scripts/modules/phenopackets/schema/v2/phenopackets.proto');
23
+ const ProtoBufRoot = Protobuf.Root.fromJSON( PhenoPacketDescriptor );
24
+ const PhenoPacket = ProtoBufRoot.lookupType('org.phenopackets.schema.v2.Phenopacket')
25
+
26
+ const ENUM_SEX = ['UNKNOWN', 'FEMALE', 'MALE', 'OTHER']
27
+ exports.ENUM_SEX = ENUM_SEX;
28
+
29
+ const ENUM_PROG_STATE = ['UNKNOWN_PROGRESS', 'IN_PROGRESS', 'COMPLETED', 'SOLVED', 'UNSOLVED']
30
+ exports.ENUM_PROG_STATE = ENUM_PROG_STATE;
31
+
32
+ const ENUM_ACMG =
33
+ ['NOT_PROVIDED', 'BENIGN', 'LIKELY_BENIGN', 'UNCERTAIN_SIGNIFICANCE', 'LIKELY_PATHOGENIC', 'PATHOGENIC'];
34
+
35
+ exports.ENUM_ACMG = ENUM_ACMG;
36
+
37
+
38
+ /************************************************************************************
39
+ * Functions for node.js only
40
+ ************************************************************************************/
41
+
42
+ try {
43
+ const FS = require( 'fs/promises' );
44
+ const { version } = require('os');
45
+
46
+ exports.generateRxomeKeyFiles = async (name = 'rxome', dir = '.') => {
47
+ const { privateKey, publicKey } = await exports.generateRxomeKeys( name );
48
+ await Promise.all([
49
+ FS.writeFile(`${dir}/${name}.private.key`, privateKey, { mode: 0o600 }, err => { console.log(err); }),
50
+ FS.writeFile(`${dir}/${name}.public.key`, publicKey, { mode: 0o600 }, function (err) { console.log(err); })
51
+ ]);
52
+ }
53
+
54
+ exports.writeQR = async ( filename, data, api = RXAPI, apiEntry = APIENTRY ) => {
55
+ const {qrData, pseudonym} = await exports.prepareQR( data, api, apiEntry );
56
+ //const base64Data = qr_code.replace(/^data:image\/png;base64,/, "");
57
+ //FS.writeFile(filename, base64Data, 'base64', (err) => {console.log(err)} );
58
+ QRCode.toFile( filename, qrData, { type: 'png'} )
59
+ return pseudonym
60
+ }
61
+ }
62
+
63
+ catch (e) {
64
+ if (e instanceof Error && e.code !== "MODULE_NOT_FOUND") {
65
+ throw e;
66
+ }
67
+ }
68
+
69
+ /************************************************************************************/
70
+
71
+
72
+ exports.generateRxomeKeys = async (name = 'rxome') => {
73
+ return { privateKey, publicKey, revocationCertificate } = await PGP.generateKey({
74
+ type: 'ecc',
75
+ curve: 'curve25519',
76
+ //type: 'rsa',
77
+ //rsaBits: 2048,
78
+ userIDs: [{ name: name, email: 'info@rxome.net' }],
79
+ passphrase: PASSPHRASE,
80
+ format: 'armored'
81
+ });
82
+ }
83
+
84
+
85
+ exports.fetchKey = async ( credentials, pseudonym = '', api = RXAPI, debug = false, apiEntry = APIENTRY ) => {
86
+ const result = await RxAPI.fetchData( `${api}/${apiEntry}/getpseudonym`, credentials, pseudonym, debug )
87
+ if ( !result.pseudonym )
88
+ result.pseudonym = pseudonym;
89
+ return result;
90
+ }
91
+ /*
92
+ yields: { key: PGP_key, version: ..., pseudonym: ... }
93
+ */
94
+
95
+
96
+ exports.fetchDemoPrivateKey = async ( credentials, api=RXTESTAPI, debug = false, apiEntry = APIENTRY ) =>
97
+ await RxAPI.fetchData( `${api}/${apiEntry}/getprivatedemokey`, credentials, '', debug )
98
+
99
+ /*
100
+ yields: { private_key: PGP_key }
101
+ */
102
+
103
+ exports.fetchRxomeKey = async ( credentials, api = RXAPI, debug = false, apiEntry = APIENTRY ) =>
104
+ await RxAPI.fetchData( `${api}/${apiEntry}/getrxomekey`, credentials, '', debug )
105
+
106
+ /*
107
+ yields: { key: PGP_key, version: ... }
108
+ */
109
+ exports.convert_to_snake_case = data => jsonKeyConverter.convert( data, { camel: false } );
110
+
111
+ exports.convertToCamelCase = data => jsonKeyConverter.convert( data, { camel: true } );
112
+
113
+ exports.compressPhenoPacket = ( data ) => {
114
+ const compressedData = {
115
+ ...data,
116
+ };
117
+ if ( data.phenotypicFeatures ) {
118
+ compressedData.compressedFeatures = {
119
+ includes: data.phenotypicFeatures.filter( feat => feat.excluded === undefined || feat.excluded === false || feat.excluded === 'false' ).map( feat => feat.type.id ),
120
+ excludes: data.phenotypicFeatures.filter( feat => feat.excluded === true || feat.excluded === 'true' ).map( feat => feat.type.id )
121
+ }
122
+ }
123
+ delete compressedData.phenotypicFeatures;
124
+ return compressedData;
125
+ }
126
+
127
+
128
+ exports.sanitizeSex = ( str ) =>
129
+ isNaN(+(str.toString()))
130
+ ? Math.max(0, ENUM_SEX.indexOf(str.toUpperCase().replace('_SEX', '')))
131
+ : +str;
132
+
133
+
134
+ exports.sanitizeProgState = ( str ) =>
135
+ isNaN(+(str.toString()))
136
+ ? Math.max(0, ENUM_PROG_STATE.indexOf(str.toUpperCase()))
137
+ : +str;
138
+
139
+
140
+ exports.sanitizeACMG = ( str ) =>
141
+ isNaN(+(str.toString()))
142
+ ? Math.max(0, ENUM_ACMG.indexOf(str.toUpperCase()))
143
+ : +str
144
+
145
+
146
+ exports.whiteListPhenoPacket = ( data ) => {
147
+ res = {};
148
+ data.id && (res.id = data.id);
149
+ data.comment && (res.comment = data.comment);
150
+ data.subject && (res.subject = data.subject);
151
+ data.phenotypicFeatures && (res.phenotypicFeatures = data.phenotypicFeatures);
152
+ data.compressedFeatures && (res.compressedFeatures = data.compressedFeatures);
153
+ data.interpretations && (res.interpretations = data.interpretations);
154
+ data.diagnosis && (res.diagnosis = data.diagnosis);
155
+ data.metaData && (res.metaData = data.metaData);
156
+ data.credentials && (res.credentials = data.credentials);
157
+ return res;
158
+ }
159
+
160
+
161
+ exports.sanitizePhenoPacket = ( data, key = '' ) => {
162
+ if ( data instanceof Object ) {
163
+ if (Array.isArray( data )) {
164
+ return data.map( x => exports.sanitizePhenoPacket(x));
165
+ } else {
166
+ let obj={};
167
+ for ( let k in data ) {
168
+ obj[k] = exports.sanitizePhenoPacket( data[k], k );
169
+ }
170
+ return obj;
171
+ }
172
+ } else {
173
+ switch( key ){
174
+ case 'sex':
175
+ return exports.sanitizeSex( data );
176
+ case 'progressStatus':
177
+ return exports.sanitizeProgState( data );
178
+ case 'acmgPathogenicityClassification':
179
+ return exports.sanitizeACMG( data );
180
+ default:
181
+ return data;
182
+ }
183
+ }
184
+ }
185
+
186
+
187
+ exports.verifyPhenoPacket = (data) => (
188
+ PhenoPacket.verify( data )
189
+ )
190
+
191
+
192
+ exports.encodePhenoPacket = (data) => (
193
+ PhenoPacket.encode( data ).finish()
194
+ )
195
+
196
+
197
+ exports.decodePhenoPacket = (data) => (
198
+ PhenoPacket.decode( data )
199
+ )
200
+
201
+
202
+ exports.encode_serial = async (publicKeyStr, message) => {
203
+ const publicKey = await PGP.readKey({ armoredKey: publicKeyStr });
204
+ const encrypted = await PGP.encrypt({
205
+ message: await PGP.createMessage({ text: message }),
206
+ encryptionKeys: publicKey,
207
+ //format: 'binary',
208
+ //signingKeys: privateKey
209
+ });
210
+ return encrypted;
211
+ }
212
+
213
+
214
+ exports.encode = async (publicKeyStr, message, binary = false) => {
215
+ return await Promise.all([
216
+ PGP.readKey({ armoredKey: publicKeyStr }),
217
+ PGP.createMessage( (binary
218
+ ? { binary: message, format: 'binary' }
219
+ : { text: message }) )
220
+ ]).then( async ([publicKey, message]) => {
221
+ const encrypted = await PGP.encrypt({
222
+ message: message,
223
+ encryptionKeys: publicKey,
224
+ format: (binary ? 'binary' : 'armored'),
225
+ // signingKeys: privateKey
226
+ });
227
+ return encrypted;
228
+ }
229
+ )
230
+ }
231
+
232
+
233
+ exports.decode_serial = async (privateKeyStr, encrypted) => {
234
+ const privateKey = await PGP.readPrivateKey( { armoredKey: privateKeyStr } );
235
+ const privateKeyDecr = await PGP.decryptKey({
236
+ privateKey: privateKey,
237
+ passphrase: PASSPHRASE
238
+ });
239
+ const message = await PGP.readMessage({
240
+ armoredMessage: encrypted
241
+ });
242
+ const { data: decrypted, signatures } = await PGP.decrypt({
243
+ message,
244
+ decryptionKeys: privateKeyDecr
245
+ });
246
+ return decrypted;
247
+ }
248
+
249
+
250
+ exports.decode = async (privateKeyStr, encrypted, binary = false) => {
251
+ return await Promise.all([
252
+ PGP.readPrivateKey({ armoredKey: privateKeyStr })
253
+ .then( (privateKey) => {
254
+ return PGP.decryptKey({
255
+ privateKey: privateKey,
256
+ passphrase: PASSPHRASE
257
+ })
258
+ }),
259
+ PGP.readMessage( (binary
260
+ ? {binaryMessage: encrypted}
261
+ : {armoredMessage: encrypted} )
262
+ )
263
+ ]).then( async ([ privateKeyDecr, message]) => {
264
+ const { data: decrypted, signatures } = await PGP.decrypt({
265
+ message,
266
+ //verificationKeys: publicKey, // optional
267
+ decryptionKeys: privateKeyDecr,
268
+ format: (binary ? 'binary' : 'utf8')
269
+ });
270
+ // check signature validity (signed messages only)
271
+ // try {
272
+ // await signatures[0].verified; // throws on invalid signature
273
+ // console.log('Signature is valid');
274
+ // } catch (e) {
275
+ // throw new Error('Signature could not be verified: ' + e.message);
276
+ // }
277
+ return decrypted;
278
+ })
279
+ }
280
+
281
+
282
+ exports.prepareQR = async ( data, api = RXAPI, apiEntry = APIENTRY ) => {
283
+ const { metaData, credentials, ...medical } = data;
284
+
285
+ const whiteListMedical = exports.whiteListPhenoPacket( medical );
286
+ const sanitizedMedical = exports.sanitizePhenoPacket( whiteListMedical );
287
+ const compressedMedical = exports.compressPhenoPacket( sanitizedMedical );
288
+ const protobufMedical = exports.encodePhenoPacket( compressedMedical );
289
+ const base64Medical = RxAPI.bufferToBase64(protobufMedical);
290
+
291
+ const key = await this.fetchKey( credentials, metaData.pseudonym || '', api, false, apiEntry );
292
+
293
+ // check:
294
+ const buff = RxAPI.base64ToBuffer( base64Medical );
295
+ const pheno = exports.decodePhenoPacket( buff );
296
+ //const medicalDeciphered = JSON.parse( JSON.stringify( pheno ));
297
+ //console.log( JSON.stringify(medicalDeciphered,' ', 2 ))
298
+
299
+ const cipher = await exports.encode( key.key, base64Medical );
300
+ //console.log( 'Cipher:', JSON.stringify(cipher) );
301
+
302
+ //delete metaData.pseudonym;
303
+ const newMetaData = Object.fromEntries(
304
+ Object.entries( metaData ).filter( ([key, val]) => key !== 'pseudonym')
305
+ )
306
+
307
+ const qrData = {
308
+ ...newMetaData,
309
+ keyver: key.version,
310
+ apiver: apiVer,
311
+ pseudonym: key.pseudonym,
312
+ payload: cipher.toString()
313
+ }
314
+ // console.log( qrData );
315
+ // console.log( "QR-Data " , JSON.stringify( qrData ).length );
316
+
317
+ return {
318
+ qrData: JSON.stringify( qrData ),
319
+ pseudonym: key.pseudonym
320
+ }
321
+ }
322
+
323
+
324
+ exports.makeQR = async ( data, api = RXAPI, apiEntry = APIENTRY ) => {
325
+ const {qrData, pseudonym} = await exports.prepareQR( data, api, apiEntry );
326
+ return {
327
+ qr_code: await QRCode.toDataURL( qrData ),
328
+ pseudonym: pseudonym,
329
+ qr_data: qrData
330
+ }
331
+ }
332
+
333
+ exports.versionStr = () => {
334
+ return 'RxOME QR Generator 1.0.0, 2022 Tom Kamphans, GeneTalk GmbH'
335
+ }
336
+
337
+
338
+ // convert .proto to .json:
339
+ // cd assets/scripts/modules/phenopackets/schema/v2
340
+ // ../../../../../../node_modules/protobufjs-cli/bin/pbjs -t json phenopackets.proto > phenopackets.json
341
+
342
+ //decode:
343
+ // /////
344
+ // const clearBufferBin = await Coder.decode(PRIVATE_KEY, '', cipherBin, true );
345
+ // const clearBin = Buffer.from (clearBufferBin, 'Binary');
346
+ // const phenoPrimeBin = Coder.decodePhenoPacket(clearBin);
347
+ // const phenoBin = JSON.parse(JSON.stringify(phenoPrimeBin));
348
+ // ////
349
+