Skip to content

Commit ede35fd

Browse files
committed
fix: cipher on android
1 parent 339d3cd commit ede35fd

File tree

4 files changed

+114
-6
lines changed

4 files changed

+114
-6
lines changed

cpp/Cipher/MGLPublicCipherInstaller.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ FieldDefinition getPublicCipherFieldDefinition(
9696
runtime, pkey, padding, digest, arguments[offset + 3], buf);
9797

9898
if (!out.has_value()) {
99-
throw jsi::JSError(runtime, "Failed to decrypt");
99+
throw jsi::JSError(runtime, "Failed Cipher Operation - " + name);
100100
}
101101

102102
return out.value().getObject(runtime);

cpp/MGLQuickCryptoHostObject.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,26 +63,29 @@ MGLQuickCryptoHostObject::MGLQuickCryptoHostObject(
6363
// publicEncrypt
6464
this->fields.push_back(
6565
getPublicCipherFieldDefinition<MGLPublicCipher::kPublic,
66-
EVP_PKEY_encrypt_init, EVP_PKEY_encrypt>(
66+
EVP_PKEY_encrypt_init,
67+
EVP_PKEY_encrypt>(
6768
"publicEncrypt", jsCallInvoker, workerQueue));
6869

6970
// privateDecrypt
7071
this->fields.push_back(
7172
getPublicCipherFieldDefinition<MGLPublicCipher::kPrivate,
72-
EVP_PKEY_decrypt_init, EVP_PKEY_decrypt>(
73+
EVP_PKEY_decrypt_init,
74+
EVP_PKEY_decrypt>(
7375
"privateDecrypt", jsCallInvoker, workerQueue));
7476

7577
// privateEncrypt
7678
this->fields.push_back(
7779
getPublicCipherFieldDefinition<MGLPublicCipher::kPrivate,
78-
EVP_PKEY_sign_init, EVP_PKEY_sign>(
80+
EVP_PKEY_sign_init,
81+
EVP_PKEY_sign>(
7982
"privateEncrypt", jsCallInvoker, workerQueue));
8083

8184
// publicDecrypt
8285
this->fields.push_back(
8386
getPublicCipherFieldDefinition<MGLPublicCipher::kPublic,
84-
EVP_PKEY_verify_recover_init,
85-
EVP_PKEY_verify_recover>(
87+
EVP_PKEY_verify_recover_init,
88+
EVP_PKEY_verify_recover>(
8689
"publicDecrypt", jsCallInvoker, workerQueue));
8790

8891
// generateKeyPair

example/src/hooks/useTestList.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import '../testing/Tests/HmacTests/HmacTests';
1010
import '../testing/Tests/HashTests/HashTests';
1111
import '../testing/Tests/CipherTests/CipherTestFirst';
1212
import '../testing/Tests/CipherTests/CipherTestSecond';
13+
import '../testing/Tests/CipherTests/test398';
1314
import '../testing/Tests/CipherTests/PublicCipherTests';
1415
import '../testing/Tests/CipherTests/generateKey';
1516
import '../testing/Tests/CipherTests/GenerateKeyPairTests';
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import type { BinaryLikeNode } from './../../../../../src/Utils';
2+
// import { Buffer } from 'buffer';
3+
import { Buffer } from '@craftzdog/react-native-buffer';
4+
import crypto from 'react-native-quick-crypto';
5+
import { describe, it } from '../../MochaRNAdapter';
6+
import { expect } from 'chai';
7+
8+
type EncryptRequest = {
9+
payload: string;
10+
publicKey: ArrayBuffer;
11+
};
12+
type EncryptResponse = {
13+
KEY: string;
14+
IV: string;
15+
PAYLOAD: string;
16+
secretKey: BinaryLikeNode;
17+
};
18+
19+
const encrypt = ({ payload, publicKey }: EncryptRequest): EncryptResponse => {
20+
const secretKey = crypto.randomBytes(16);
21+
const iv = crypto.randomBytes(16);
22+
23+
const cipher = crypto.createCipheriv('aes-128-gcm', secretKey, iv);
24+
25+
const encryptedPayload = Buffer.concat([
26+
cipher.update(payload),
27+
cipher.final(),
28+
cipher.getAuthTag(),
29+
]).toString('base64');
30+
31+
const encryptedSessionKey = crypto.publicEncrypt(
32+
{
33+
key: publicKey,
34+
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
35+
},
36+
secretKey
37+
);
38+
39+
return {
40+
KEY: encryptedSessionKey.toString('base64'),
41+
IV: iv.toString('base64'),
42+
PAYLOAD: encryptedPayload,
43+
secretKey,
44+
};
45+
};
46+
47+
const decrypt = ({
48+
response,
49+
secretKey,
50+
}: {
51+
response: EncryptResponse;
52+
secretKey: BinaryLikeNode;
53+
}) => {
54+
const { IV, PAYLOAD } = response;
55+
56+
const decipher = crypto.createDecipheriv(
57+
'aes-128-gcm',
58+
secretKey,
59+
Buffer.from(IV, 'base64')
60+
);
61+
62+
const encryptedPayload = Buffer.from(PAYLOAD, 'base64');
63+
let decrypted = decipher.update(
64+
Buffer.from(encryptedPayload.subarray(0, encryptedPayload.length - 16))
65+
);
66+
decrypted = Buffer.concat([decrypted, decipher.final()]);
67+
68+
return JSON.parse(decrypted.toString('utf8'));
69+
};
70+
71+
const getPublicKeyInPEMFormat = (key: string): ArrayBuffer => {
72+
return crypto
73+
.createPublicKey({
74+
key: Buffer.from(key, 'base64'),
75+
format: 'der',
76+
type: 'spki',
77+
})
78+
.export({
79+
type: 'spki',
80+
format: 'pem',
81+
});
82+
};
83+
84+
// export { decrypt, encrypt, getPublicKeyInPEMFormat };
85+
86+
describe('test398', () => {
87+
it('test398', () => {
88+
const publicKeySpkiBase64 =
89+
'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENlFpbMBNfCY6Lhj9A/clefyxJVIXGJ0y6CcZ/cbbyyebvN6T0aNPvpQyFdUwRtYvFHlYbqIZOM8AoqdPcnSMIA==';
90+
91+
const publicKey = getPublicKeyInPEMFormat(publicKeySpkiBase64);
92+
console.log({ publicKey });
93+
const encrypted = encrypt({
94+
payload: JSON.stringify({ a: 1 }),
95+
publicKey,
96+
});
97+
console.log({ encrypted });
98+
const { response: decrypted } = decrypt({
99+
response: encrypted,
100+
secretKey: encrypted.secretKey,
101+
});
102+
expect(decrypted).to.equal({ a: 1 });
103+
});
104+
});

0 commit comments

Comments
 (0)