Skip to content

Commit

Permalink
refactor(INJI-449): replace crypto-js with node-forge for encryption/…
Browse files Browse the repository at this point in the history
…decryption (mosip#1034)

* refactor(INJI-449): replace crypo-js with node-forge

crypto-js has vulneraribitiles prior to version 4.2.0 for encryption / decryption & 4.x.x version is not compatible with our react native project For this reason we had to move to different library for encryption / decryption

Co-authored-by: Sreenadh S <[email protected]>
Signed-off-by: Kiruthika Jeyashankar <[email protected]>

* fix(INJI-449): secure-keystore warning popup shown on reload of app

settings key which was stored in storage was not loaded into settings machine context correctly, which caused the bug - on reload settings related flows was falling back to initial setting.

Co-authored-by: Sreenadh S <[email protected]>

Signed-off-by: Kiruthika Jeyashankar <[email protected]>

* refactor(INJI-449): gitignore automation test results

Signed-off-by: Kiruthika Jeyashankar <[email protected]>

* refactor(INJI-449): simplify usage of methods in node-forge

Signed-off-by: Kiruthika Jeyashankar <[email protected]>

---------

Signed-off-by: Kiruthika Jeyashankar <[email protected]>
Co-authored-by: Sreenadh S <[email protected]>
  • Loading branch information
KiruthikaJeyashankar and sree96 authored Nov 29, 2023
1 parent 4dc60ac commit 33be025
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 60 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,12 @@ android/app/debug.keystore
.expo
dist/
web-build/

# automation test results
# test reports generated after running test
injitest/report/
injitest/testng-report/
# logs from tests ran
injitest/src/logs/
# test case class files
injitest/target/
6 changes: 4 additions & 2 deletions .talismanrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ fileignoreconfig:
- filename: package.json
checksum: fdd5905228a1afbfb004c710fd6c61adf073a12840200327c0592b76bea5e7e3
- filename: package-lock.json
checksum: 489ccd69f2deecedb8b2ff9a3a02d74c704dfba01fdfb6179316a9df698c4562
checksum: 3d98844cbc77fe3721077ea606713cd5adc2f238db1bbc10081141a7e4cd06a9
- filename: lib/jsonld-signatures/suites/ed255192018/ed25519.ts
checksum: 493b6e31144116cb612c24d98b97d8adcad5609c0a52c865a6847ced0a0ddc3a
- filename: components/PasscodeVerify.tsx
checksum: 14654c0f038979fcd0d260170a45894a072f81e0767ca9a0e66935d33b5cc703
- filename: i18n.ts
Expand Down Expand Up @@ -57,7 +59,7 @@ fileignoreconfig:
- filename: shared/openId4VCI/Utils.ts
checksum: ba3041b2ce380f44f6f52dc2c3df337d857df4494bd3c8727df9bf6fb5734750
- filename: shared/cryptoutil/cryptoUtil.ts
checksum: b785ff3f01ab9530119072c4d38195048bfeee6155c54ea7dd031559acb722f3
checksum: 350524d0d0d18993903b056a1d0a396ec2b2566b6531fd83bd7cafce06d1c332
- filename: machines/store.typegen.ts
checksum: 6d22bc5c77398316b943c512c208ce0846a9fff674c1ccac79e07f21962acd5f
- filename: machines/VCItemMachine/ExistingMosipVCItem/ExistingMosipVCItemMachine.typegen.ts
Expand Down
142 changes: 108 additions & 34 deletions lib/jsonld-signatures/suites/ed255192018/ed25519.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
/*!
* Copyright (c) 2020 Digital Bazaar, Inc. All rights reserved.
*/
import { Buffer } from 'buffer';
import {Buffer} from 'buffer';

// FIXME: Some methods is missing from crypto-js.
import {
sign,
verify,
createPrivateKey,
createPublicKey,
randomBytes,
} from 'crypto-js';
import forge, {pki, asn1, util, random, md} from 'node-forge';

type PrivateKey = forge.pki.PrivateKey;
type PublicKey = forge.pki.PublicKey;

const {
publicKeyToAsn1,
publicKeyFromAsn1,
privateKeyToAsn1,
privateKeyFromAsn1,
ed25519,
} = pki;
const {toDer, fromDer: forgeFromDer} = asn1;
const {createBuffer} = util;
const {getBytesSync: getRandomBytes} = random;
const {sha256} = md;

// used to export node's public keys to buffers
const publicKeyEncoding = { format: 'der', type: 'spki' };
const publicKeyEncoding = {format: 'der', type: 'spki'};
// used to turn private key bytes into a buffer in DER format
const DER_PRIVATE_KEY_PREFIX = Buffer.from(
'302e020100300506032b657004220420',
'hex'
'hex',
);
// used to turn public key bytes into a buffer in DER format
const DER_PUBLIC_KEY_PREFIX = Buffer.from('302a300506032b6570032100', 'hex');
Expand All @@ -31,15 +39,18 @@ const api = {
* @returns {object} The object with the public and private key material.
*/
async generateKeyPairFromSeed(seedBytes) {
const privateKey = await createPrivateKey({
// node is more than happy to create a new private key using a DER
key: _privateKeyDerEncode({ seedBytes }),
format: 'der',
type: 'pkcs8',
});
const privateKey: PrivateKey = forgePrivateKey(
_privateKeyDerEncode({seedBytes}),
);

// this expects either a PEM encoded key or a node privateKeyObject
const publicKey = await createPublicKey(privateKey);
const publicKeyBuffer = publicKey.export(publicKeyEncoding);
const publicKey: PublicKey =
createForgePublicKeyFromPrivateKeyBuffer(privateKey);
const publicKeyBuffer: Buffer = Buffer.from(
toDer(publicKeyToAsn1(publicKey)).getBytes(),
'binary',
);

const publicKeyBytes = getKeyMaterial(publicKeyBuffer);
return {
publicKey: publicKeyBytes,
Expand All @@ -52,25 +63,88 @@ const api = {
return api.generateKeyPairFromSeed(seed);
},
async sign(privateKeyBytes, data) {
const privateKey = await createPrivateKey({
key: _privateKeyDerEncode({ privateKeyBytes }),
format: 'der',
type: 'pkcs8',
});
return sign(null, data, privateKey);
const privateKey: PrivateKey = forgePrivateKey(
_privateKeyDerEncode({privateKeyBytes}),
);
const signature: string = forgeSign(data, privateKey);

return signature;
},
async verify(publicKeyBytes, data, signature) {
const publicKey = await createPublicKey({
key: _publicKeyDerEncode({ publicKeyBytes }),
format: 'der',
type: 'spki',
});
return verify(null, data, publicKey, signature);
async verify(publicKeyBytes: Uint8Array, data: string, signature: string) {
const publicKey = await createForgePublicKeyFromPublicKeyBuffer(
_publicKeyDerEncode({publicKeyBytes}),
);
return forgeVerifyEd25519(data, publicKey, signature);
},
};

export default api;

function forgePrivateKey(privateKeyBuffer: Buffer): PrivateKey {
return privateKeyFromAsn1(fromDer(privateKeyBuffer));
}

function fromDer(keyBuffer: Buffer) {
return forgeFromDer(keyBuffer.toString('binary'));
}

function createForgePublicKeyFromPrivateKeyBuffer(
privateKeyObject: PrivateKey,
): PublicKey {
const privateKeyBuffer = privateKeyToBuffer(privateKeyObject);
const publicKey = ed25519.publicKeyFromPrivateKey({
privateKey: privateKeyBuffer,
});
return publicKey;
}

function createForgePublicKeyFromPublicKeyBuffer(
publicKeyBuffer: Buffer,
): string {
const publicKeyObject = publicKeyFromAsn1(fromDer(publicKeyBuffer));
const publicKeyDer = toDer(publicKeyToAsn1(publicKeyObject)).getBytes();

return publicKeyDer;
}

function forgeSign(data: string, privateKeyObject: PrivateKey): string {
const privateKeyBytes = toDer(privateKeyToAsn1(privateKeyObject)).getBytes();

const privateKey = createBuffer(privateKeyBytes);

const signature = ed25519.sign({
privateKey,
md: sha256.create(),
message: data,
});

return signature.toString('binary');
}

function forgeVerifyEd25519(
data: string,
publicKey: string,
signature: string,
): boolean {
return ed25519.verify({
publicKey: publicKey,
signature: createBuffer(signature),
message: createBuffer(data),
});
}

function randomBytes(length: number) {
return Buffer.from(getRandomBytes(length), 'binary');
}

function privateKeyToBuffer(privateKey: PrivateKey): Buffer {
const privateKeyAsn1 = privateKeyToAsn1(privateKey);
const privateKeyDer = toDer(privateKeyAsn1).getBytes();

const privateKeyBuffer = Buffer.from(privateKeyDer, 'binary');

return privateKeyBuffer;
}
/**
* The key material is the part of the buffer after the DER Prefix.
*
Expand Down Expand Up @@ -103,7 +177,7 @@ function getKeyMaterial(buffer) {
*
* @returns {Buffer} DER private key prefix + key bytes.
*/
export function _privateKeyDerEncode({ privateKeyBytes, seedBytes }: any) {
export function _privateKeyDerEncode({privateKeyBytes, seedBytes}: any) {
if (!(privateKeyBytes || seedBytes)) {
throw new TypeError('`privateKeyBytes` or `seedBytes` is required.');
}
Expand Down Expand Up @@ -141,7 +215,7 @@ export function _privateKeyDerEncode({ privateKeyBytes, seedBytes }: any) {
*
* @returns {Buffer} DER Public key Prefix + key bytes.
*/
export function _publicKeyDerEncode({ publicKeyBytes }) {
export function _publicKeyDerEncode({publicKeyBytes}) {
if (!(publicKeyBytes instanceof Uint8Array && publicKeyBytes.length === 32)) {
throw new TypeError('`publicKeyBytes` must be a 32 byte Buffer.');
}
Expand Down
8 changes: 4 additions & 4 deletions machines/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,17 +319,17 @@ export const appMachine = model.createMachine(

loadCredentialRegistryInConstants: (_context, event) => {
changeCrendetialRegistry(
!event.response?.credentialRegistry
!event.response?.encryptedData?.credentialRegistry
? MIMOTO_BASE_URL
: event.response?.credentialRegistry,
: event.response?.encryptedData?.credentialRegistry,
);
},

loadEsignetHostFromConstants: (_context, event) => {
changeEsignetUrl(
!event.response?.esignetHostUrl
!event.response?.encryptedData?.esignetHostUrl
? ESIGNET_BASE_URL
: event.response?.esignetHostUrl,
: event.response?.encryptedData?.esignetHostUrl,
);
},
},
Expand Down
3 changes: 2 additions & 1 deletion machines/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ export const settingsMachine = model.createMachine(
__AppId.setValue(newContext.appId);
return {
...context,
...newContext,
...newContext.encryptedData,
appId: newContext.appId,
};
}),

Expand Down
30 changes: 19 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
"@xstate/react": "^3.0.1",
"base64url-universal": "^1.1.0",
"buffer": "^6.0.3",
"crypto-js": "^3.3.0",
"date-fns": "^2.26.0",
"expo": "~48.0.18",
"expo-app-loading": "~1.3.0",
Expand Down Expand Up @@ -93,6 +92,7 @@
"@react-native-community/eslint-config": "^3.2.0",
"@react-navigation/devtools": "^6.0.19",
"@tsconfig/react-native": "^2.0.2",
"@types/node-forge": "^1.3.9",
"@types/react": "^18.0.24",
"@types/react-native": "~0.64.12",
"@typescript-eslint/eslint-plugin": "^5.17.0",
Expand Down
Loading

0 comments on commit 33be025

Please sign in to comment.