Closed hongfeiyang closed 4 years ago
Hello and thanks for the feature request.
Can you describe what do you want to achieve ? As I understand it, you want to encode / decode RSA private and public keys to and from PKCS#1 format ?
Is this correct ?
Yes that's correct. I have read through how the package form RSA keys from pkcs8 Pem string and convert RSA keys to pkcs8 pem string, and I used some of your source code to achieve PKCS1 formatting, however it would be good if this function is included in the package
Yes this sounds like a good idea. I will try to implement this maybe next week. If you already have some working code,feel free to create a pull request :).
@hongfeiyang One step is done, please update to 2.6.1 to use the following methods from the CryptoUtils class:
String encodeRSAPrivateKeyToPemPkcs1(RSAPrivateKey rsaPrivateKey);
String encodeRSAPublicKeyToPemPkcs1(RSAPublicKey rsaPublicKey);
The next step is to create a RSAPrivateKey and RSAPublicKey from a given PEM string.
@Ephenodrom Thanks :)
@Ephenodrom I would like to share with you the code I used to convert RSA keys to PKCS1 strings back and forth, I don't know how are going you going to change the underlying structure so I did not create a pull request, but I hope this could be helpful
+String encodeRSAPrivateKeyToPKCS1PemString(RSAPrivateKey privateKey) {
+ var privateKeySeq = ASN1Sequence();
+ var version = ASN1Integer(BigInt.from(0));
+ 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 dataBase64 = base64.encode(privateKeySeq.encodedBytes);
Add a comment to this line
+ var chunks = StringUtils.chunk(dataBase64, 64);
+ return """-----BEGIN RSA PRIVATE KEY-----\n${chunks.join('\n')}\n-----END RSA PRIVATE KEY-----""";
+}
+
+String encodeRSAPublicKeyToPKCS1PemString(RSAPublicKey publicKey) {
+ var publicKeySeq = ASN1Sequence();
+ publicKeySeq.add(ASN1Integer(publicKey.modulus));
+ publicKeySeq.add(ASN1Integer(publicKey.exponent));
+
+ var dataBase64 = base64.encode(publicKeySeq.encodedBytes);
+ var chunks = StringUtils.chunk(dataBase64, 64);
+
+ return """-----BEGIN RSA PUBLIC KEY-----\n${chunks.join('\n')}\n-----END RSA PUBLIC KEY-----""";
+}
+
+RSAPublicKey loadRSAPublicKeyFromPKCS8PemString(String pem) {
return X509Utils.publicKeyFromPem(pem);
}
+
+RSAPrivateKey loadRSAPrivateKeyFromPKCS1PemString(String pem) {
+ var bytes = X509Utils.getBytesFromPEMString(pem);
+ var asn1Parser = ASN1Parser(bytes);
+ var pkSeq = asn1Parser.nextObject() as ASN1Sequence;
+
+ var modulus = pkSeq.elements[1] as ASN1Integer;
+ //ASN1Integer publicExponent = pkSeq.elements[2] as ASN1Integer;
+ var privateExponent = pkSeq.elements[3] as ASN1Integer;
+ var p = pkSeq.elements[4] as ASN1Integer;
+ var q = pkSeq.elements[5] as ASN1Integer;
+ //ASN1Integer exp1 = pkSeq.elements[6] as ASN1Integer;
+ //ASN1Integer exp2 = pkSeq.elements[7] as ASN1Integer;
+ //ASN1Integer co = pkSeq.elements[8] as ASN1Integer;
+
+ var rsaPrivateKey = RSAPrivateKey(
+ modulus.valueAsBigInteger,
+ privateExponent.valueAsBigInteger,
+ p.valueAsBigInteger,
+ q.valueAsBigInteger);
+
+ return rsaPrivateKey;
+}
+
+RSAPublicKey loadRSAPublicKeyFromPKCS1PemString(String pem) {
+ var bytes = X509Utils.getBytesFromPEMString(pem);
+ var publicKeyAsn = ASN1Parser(bytes);
+ ASN1Sequence publicKeySeq = publicKeyAsn.nextObject();
+ var modulus = publicKeySeq.elements[0] as ASN1Integer;
+ var exponent = publicKeySeq.elements[1] as ASN1Integer;
+
+ var rsaPublicKey =
+ RSAPublicKey(modulus.valueAsBigInteger, exponent.valueAsBigInteger);
+ return rsaPublicKey;
+}
@hongfeiyang Please update to version 2.6.2.
These are all methods from the CryptoUtils class that should cover your feature request. Thanks for the code, i used some of that and added unit tests.
String encodeRSAPrivateKeyToPemPkcs1(RSAPrivateKey rsaPrivateKey);
String encodeRSAPublicKeyToPemPkcs1(RSAPublicKey rsaPublicKey);
RSAPublicKey rsaPublicKeyFromPemPkcs1(String pem);
RSAPrivateKey rsaPrivateKeyFromPemPkcs1(String pem);
RSAPublicKey rsaPublicKeyFromDERBytesPkcs1(Uint8List bytes);
RSAPrivateKey rsaPrivateKeyFromDERBytesPkcs1(Uint8List bytes);
Is there any support for PKCS#1 format keys in the future? I see the current implementation only supports PKCS#8 format keys, it would be a great addition to the existing functionalities in the package.