Closed meyerjoe closed 4 years ago
Hi, Thank you for showing interest in rsa_encrypt. I created rsa_encrypt to implement end-to-end encryption in my app and it does its job quite good. Thus, I don't think there's much that I can do because originally rsa_encrypt was made to be used internally: "You can only encrypt data and decrypt it in the app itself. The private & public key will only WORK INSIDE THE APP. I don't know your situation but you can encrypt data and send it directly to firestore. and decrypt it only when the data arrives". NOTE: rsa_encrypt uses MIT License so you can modify the source code to match your needs. Happy Coding :)
On Mon, Jun 15, 2020 at 8:48 PM meyerjoe notifications@github.com wrote:
If I try to import the PEM file anywhere else, I get error messages.
The reason is, that the wrong tag is used.
Instead of
-----BEGIN PRIVATE KEY----- BASE64 ENCODED DATA -----END PRIVATE KEY-----
it should be
-----BEGIN RSA PRIVATE KEY----- BASE64 ENCODED DATA -----END RSA PRIVATE KEY-----
see here for further info:
Apart from that, I haven't managed yet to use the key on node.js (Firebase Function) and encrypt something, that could be decrypted properly in Flutter.
Here is the code on node.js (version 10)
` import as functions from 'firebase-functions'; import as admin from 'firebase-admin'; import * as crypto from 'crypto';
export const encrypt = async function(data: any, context: functions.https.CallableContext) {
// ... fetch public key from Firestore
const publicKeyPem = "-----BEGIN RSA PUBLIC KEY-----\n" + "MIICCgKCAgEA1w3+f0DcF+XjBYy3usSRKRTpqREGhpv0Wqh5GK0UAdKXaPpkc9WQ6yJJH2iAE0Rm4nCqs+S8qkCzHUA+c3KSyLGqokLKy7fv49juExkGL4gZNXU8ql8lF1C6QPZBE+FF9JZd4ExoKWKgttWlTU6eYU8+eZD0BrHfLiKwE8YBLc2zKHKWVSscll027jkUynp4AJFjW9q2yRcCkGwDnt2QfAXMZqBfZlXxpyTTSIkfKJ/U7BKrJqObh7ZnrJMd/9qmAXa8XbAQCzxe+pU40q3Q+faJzcfEgkysM1F1myBZjHqQH83XsyNeyvJv8+SVO9Yqs/9TeuHr+tXDQCTiOhMW9/wvMVtkHvaWYhGPN/QW4i1EYzOdsw74o/4ffPhwQIGXTaCwW7D+AWuOEXAqo2OyFaaY5inXAEJglFLzpqlSyL25HGp8qDd637YPyA/ccOmVQp3asbRRiTpvclriLbQ6oHpfuWUTAHLRZhL1qKVaPzd9phK5Rs3fuanNgHhXeyFvyIPA4CwOCwFBon/eP2fWVh2XyOCnJORLFmMc2mXMVess1+9qmXWJnXXdHHgVFU5jxZQ6WDo9IA2eJVmEfy6mH0uEXzA9oEwDSEXH0LpZTSuIaWa+CFz0iw/TCJGsCQw0sOBkVPbz9ZdbgLFaW72tXTWyXFvredqyGXPZl/frq+kCAwEAAQ==" + "\n-----END RSA PUBLIC KEY-----"
String encryptionResult = crypto.publicEncrypt({ key: publicKeyPem }, Buffer.from("my sensitive data")).toString('base64');
// ... store encryptionResult in Firestore
}
`
In Flutter, I do the following:
` // retrieve encryptionResult from Firestore
var stringInUtf = utf8.decode(base64Decode(encryptionResult));
var decryptedStr = decrypt(stringInUtf, privateKey);
`
I'd be very grateful for a hint how to solve this.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/AbdelbakiBoukerche/rsa_encrypt/issues/1, or unsubscribe https://github.com/notifications/unsubscribe-auth/ALB4GWMVZWLU6VSYLBFIXDTRWZ3KBANCNFSM4N6RHXQA .
thx for the quick reply!
@meyerjoe did you get a solution for this?
yes, I got it solved. If I remember correctly, the generated string of this library did not adhere to the standard PEM encoding. It works if you just use this library for encrypting and decrypting, but not, if you use it together with a different lib (e.g. on the server), which expects the standard.
that's why I ended up with this implementation:
import 'package:pointycastle/api.dart';
import 'package:pointycastle/asymmetric/api.dart';
import "package:pointycastle/export.dart";
import "package:asn1lib/asn1lib.dart";
encodePublicKeyToPem(RSAPublicKey publicKey) {
var algorithmSeq = new ASN1Sequence();
var algorithmAsn1Obj = new ASN1Object.fromBytes(
Uint8List.fromList([0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x1]));
var paramsAsn1Obj = new ASN1Object.fromBytes(Uint8List.fromList([0x5, 0x0]));
algorithmSeq.add(algorithmAsn1Obj);
algorithmSeq.add(paramsAsn1Obj);
var publicKeySeq = new ASN1Sequence();
publicKeySeq.add(ASN1Integer(publicKey.modulus));
publicKeySeq.add(ASN1Integer(publicKey.exponent));
var publicKeySeqBitString = new ASN1BitString(Uint8List.fromList(publicKeySeq.encodedBytes));
var topLevelSeq = new ASN1Sequence();
topLevelSeq.add(algorithmSeq);
topLevelSeq.add(publicKeySeqBitString);
var dataBase64 = base64.encode(topLevelSeq.encodedBytes);
return """-----BEGIN PUBLIC KEY-----\r\n$dataBase64\r\n-----END PUBLIC KEY-----""";
}
encodePrivateKeyToPem(RSAPrivateKey privateKey) {
var version = ASN1Integer(BigInt.from(0));
var algorithmSeq = new ASN1Sequence();
var algorithmAsn1Obj = new ASN1Object.fromBytes(
Uint8List.fromList([0x6, 0x9, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0xd, 0x1, 0x1, 0x1]));
var paramsAsn1Obj = new ASN1Object.fromBytes(Uint8List.fromList([0x5, 0x0]));
algorithmSeq.add(algorithmAsn1Obj);
algorithmSeq.add(paramsAsn1Obj);
var privateKeySeq = new ASN1Sequence();
var modulus = ASN1Integer(privateKey.n);
var publicExponent = ASN1Integer(BigInt.parse('65537'));
var privateExponent = ASN1Integer(privateKey.d);
var p = ASN1Integer(privateKey.p);
var q = ASN1Integer(privateKey.q);
var dP = privateKey.d % (privateKey.p - BigInt.from(1));
var exp1 = ASN1Integer(dP);
var dQ = privateKey.d % (privateKey.q - BigInt.from(1));
var exp2 = ASN1Integer(dQ);
var iQ = privateKey.q.modInverse(privateKey.p);
var co = ASN1Integer(iQ);
privateKeySeq.add(version);
privateKeySeq.add(modulus);
privateKeySeq.add(publicExponent);
privateKeySeq.add(privateExponent);
privateKeySeq.add(p);
privateKeySeq.add(q);
privateKeySeq.add(exp1);
privateKeySeq.add(exp2);
privateKeySeq.add(co);
var publicKeySeqOctetString =
new ASN1OctetString(Uint8List.fromList(privateKeySeq.encodedBytes));
var topLevelSeq = new ASN1Sequence();
topLevelSeq.add(version);
topLevelSeq.add(algorithmSeq);
topLevelSeq.add(publicKeySeqOctetString);
var dataBase64 = base64.encode(topLevelSeq.encodedBytes);
return """-----BEGIN PRIVATE KEY-----\r\n$dataBase64\r\n-----END PRIVATE KEY-----""";
}
@meyerjoe Thank you very much. @AbdelbakiBoukerche can we have this improvement added to the package?
If I try to import the PEM file anywhere else, I get error messages.
The reason is, that the wrong tag is used.
Instead of
-----BEGIN PRIVATE KEY----- BASE64 ENCODED DATA -----END PRIVATE KEY-----
it should be
-----BEGIN RSA PRIVATE KEY----- BASE64 ENCODED DATA -----END RSA PRIVATE KEY-----
see here for further info: https://stackoverflow.com/questions/20065304/differences-between-begin-rsa-private-key-and-begin-private-key
https://stackoverflow.com/questions/18039401/how-can-i-transform-between-the-two-styles-of-public-key-format-one-begin-rsa
Apart from that, I haven't managed yet to use the key on node.js (Firebase Function) and encrypt something, that could be decrypted properly in Flutter.
Here is the code on node.js (version 10)
` import as functions from 'firebase-functions'; import as admin from 'firebase-admin'; import * as crypto from 'crypto';
export const encrypt = async function(data: any, context: functions.https.CallableContext) {
// ... fetch public key from Firestore
const publicKeyPem = "-----BEGIN RSA PUBLIC KEY-----\n" + "MIICCgKCAgEA1w3+f0DcF+XjBYy3usSRKRTpqREGhpv0Wqh5GK0UAdKXaPpkc9WQ6yJJH2iAE0Rm4nCqs+S8qkCzHUA+c3KSyLGqokLKy7fv49juExkGL4gZNXU8ql8lF1C6QPZBE+FF9JZd4ExoKWKgttWlTU6eYU8+eZD0BrHfLiKwE8YBLc2zKHKWVSscll027jkUynp4AJFjW9q2yRcCkGwDnt2QfAXMZqBfZlXxpyTTSIkfKJ/U7BKrJqObh7ZnrJMd/9qmAXa8XbAQCzxe+pU40q3Q+faJzcfEgkysM1F1myBZjHqQH83XsyNeyvJv8+SVO9Yqs/9TeuHr+tXDQCTiOhMW9/wvMVtkHvaWYhGPN/QW4i1EYzOdsw74o/4ffPhwQIGXTaCwW7D+AWuOEXAqo2OyFaaY5inXAEJglFLzpqlSyL25HGp8qDd637YPyA/ccOmVQp3asbRRiTpvclriLbQ6oHpfuWUTAHLRZhL1qKVaPzd9phK5Rs3fuanNgHhXeyFvyIPA4CwOCwFBon/eP2fWVh2XyOCnJORLFmMc2mXMVess1+9qmXWJnXXdHHgVFU5jxZQ6WDo9IA2eJVmEfy6mH0uEXzA9oEwDSEXH0LpZTSuIaWa+CFz0iw/TCJGsCQw0sOBkVPbz9ZdbgLFaW72tXTWyXFvredqyGXPZl/frq+kCAwEAAQ==" + "\n-----END RSA PUBLIC KEY-----"
String encryptionResult = crypto.publicEncrypt({ key: publicKeyPem }, Buffer.from("my sensitive data")).toString('base64');
// ... store encryptionResult in Firestore
}
`
In Flutter, I do the following:
` // retrieve encryptionResult from Firestore
var stringInUtf = utf8.decode(base64Decode(encryptionResult));
var decryptedStr = decrypt(stringInUtf, privateKey);
`
I'd be very grateful for a hint how to solve this.