Dear TMS team,
Dear Marion,
Thank you very for your very quick answer.
I first found out that I have to create the RSA parameters in .NET as there are additional fields needed in the RSACryptoServiceProvider to generate an object with an existing RSA key. Please have a look at the following code generating the 2048 bits key parameters and exporting it to the console.
public static void GenerateKeyString()
{
var cryptoServiceProvider = new RSACryptoServiceProvider(2048);
var rsaParameters = cryptoServiceProvider.ExportParameters(true);
var stringWriter = new System.IO.StringWriter();
var xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
xmlSerializer.Serialize(stringWriter, rsaParameters);
Console.WriteLine(stringWriter.ToString());
}
Executing the console application will give me the following XML representation of the RSA key parameters.
<?xml version="1.0" encoding="utf-16"?>
<RSAParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Exponent>AQAB</Exponent>
<Modulus>uzbtMdjXwkhvggQctl7TLg/YkM1UxHLqtj8zcntD/O/M+T/gCpMYRFjgHaM9+c1PwCFkG5yBw5VB0nxKUjoAnSo1K9PgGSHWUk4WRXtNrIRkUITQGQsU3GPLDHDzbu0w4+1v/UGE7POK5i3f64g70VdtwjQ3v7pa2soTWd/Mgah7WO33lJKC8RgM9HDo54874YFnFT+vgfP5wRYNHTb3UEITS/+qE4xooZtR0vzgWXymkb1f4MPFh5pm5S9dnAI5qRI2iqowYdpUitZAnnOPfR2lmQLeyH4D2wX6GycgnzFK5N6994jQl+Dn/qy8UbNUP647z5cl8KLfYtNZCg46ZQ==</Modulus>
<P>4mF96uxly2vdKzwDdIGpe4rWzvSk9v/hu5shAoyy7CF0Cimjo+0irOaQOzZNfczp8ipjtQJoFFm/PovSr+sOn00V58bVTcf9YZZf7yDmWAYTO3rQPY9wc0oIm0q8ncpdhg3dkNqMuxg9Vzl5Y/G/foty9zcv3Ph2FVkc+ATOfRs=</P>
<Q>07WUrxYBow0Blwpa4f5xi75z1bASQhrz+8qmQgX2JwUPyhQ7Ayt8snLDpngpuuvmtGZ7j3SaS0Ce+Y1rrlyb8rzqdijqOrwwpuGlrIHl79vwCkoUmb6Xmw+Grx5kCRwCwHW1nnvBDoPDIJyo+uHdsoBXcfRJRmOiGHPomUcvHn8=</Q>
<DP>WRvxGbkF9MW3oF4WKhUj5opnNb2c9dERROyyWLOTdllQuPNdA5jDbnWvTm94n006xWUkLEsPNvuAyRj2zOJkthX8ymg87EoNlg1AI/u6T+nMRjx4ndLJe8gnjSElD6Npnuv0TCGLBdZrxtrLyqiNLT2s+lzRzVRL/uk9+u7BbQM=</DP>
<DQ>uHYH/J3CA107u2yMT0ixij8BEnj9D5gIaaTiQ7iKBumEHmCOIm7rkVgpXIxqX7FXLGv20MGaBmNhoLI11pBeWJt99kIkA9Ug1ubYwXvU6q7JcU2msWa9FZ/ri/2Az+cWBrcI7fOJ/KmVhH67RQ0za2ojxuhASBJbk866JYM+bOU=</DQ>
<InverseQ>O0mybCngn3qkItEfCxwOT0ayyye+ygJxZJ0sU9SncCfcREf/ecWAfpDjQNSUmOFph+JBUMkrgGYtGja7Ht976VW5m66pgAXUmIouAlO/R+J4cNHMGWUW42xrYfTxhYnsY5Yfbijy4O685lR/c1iXeg8ArGFblblniQEjLs7Tbb4=</InverseQ>
<D>Km9lzmGvbjtLAzZ5Z6EQzyUKWrAgIbNGnm6u86kbHQ8h7/FZkCwNWRioHC+vUZsHE6696UBNbY68b8B6fC7nirhRexC4gBnaYaePhspPLeaIcnPYU4TegqIgGT7U/vTGmzNrqgUa4zbE6i3FzrZ/kJD3sQhzBoNwKp2ZS0reKRkrJyVZDVO0fRfHZLOS+d4uOb5XzngwFmmWcunlrPpCmG+mDUbQTR5Dd12x/qVI/LNgANJXdl4/A0ob9WA4D98agITkCyFbUXTHfZBLhTtCkNammAcCfPCV6HWFl52+I3VFP+SHfOZLS/Zwlc/fJ0BPVGi0izy+KvtRC3qsZtmPlQ==</D>
</RSAParameters>
In my opinion the <Modulus> element contains the RSA modulus in Base64 encoding, the <Exponent> element contains the RSA public exponent in Base64 encoding and the <D> element contains the RSA private exponent in Base64 encoding.
Now I am using the modulus and private exponent in Delphi to construct a RSA object and encrypt a string.
uses
System.SysUtils, RSAObj, MiscObj;
procedure Encrypt(Value: string);
var
RSA: TRSAEncSign;
begin
RSA := TRSAEncSign.Create;
RSA.keyLength := kl2048;
RSA.encType := oaep;
RSA.outputFormat := base64;
RSA.modulus := 'uzbtMdjXwkhvggQctl7TLg/YkM1UxHLqtj8zcntD/O/M+T/gCpMYRFjgHaM9+c1PwCFkG5yBw5VB0nxKUjoAnSo1K9PgGSHWUk4WRXtNrIRkUITQGQsU3GPLDHDzbu0w' +
'4+1v/UGE7POK5i3f64g70VdtwjQ3v7pa2soTWd/Mgah7WO33lJKC8RgM9HDo54874YFnFT+vgfP5wRYNHTb3UEITS/+qE4xooZtR0vzgWXymkb1f4MPFh5pm5S9dnAI5' +
'qRI2iqowYdpUitZAnnOPfR2lmQLeyH4D2wX6GycgnzFK5N6994jQl+Dn/qy8UbNUP647z5cl8KLfYtNZCg46ZQ==';
RSA.PublicExponent := 'AQAB';
WriteLn(RSA.Encrypt(Value));
end;
begin
try
Encrypt('Test');
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
This will output the following cipher text for ?Test? in Base64 encoding on the console.
WFySQ7+NYeNhwW7k6ULiekuN6fTqpEqoMh7P5L2Ap+oE4NphkXj9sleFKLpHgHBVSCCzAgWL8uhaXu/jCR4tv/146wtucWCIqupya38K9ybz3PE48Dwk6y4bn6KleLDqvhs8SXNaV1k/s0b8zveumWspB85F96SBiZlwGxBbSX63mdIRdTX064xGY4G6EmeayvzHp2iSf7kimYzu9X3R/2gBW7ppbzl8CcS3sGZkrxgBfpZPvFdKsAY8vbXNuwXhDwSunyvPWJR+Mq0g70kU2ckSIJ/lA5MtabCYNN4o1kl3oHEcS6Y2Y2pQIM5xkVGuTBnXAA7JI6Lrj/U3jfNqMw==
In .NET I do the same encryption with the generate key like in the following code snippet.
private static void Encrypt(string value)
{
var cryptoServiceProvider = new RSACryptoServiceProvider(2048);
cryptoServiceProvider.FromXmlString("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<RSAParameters xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <Exponent>AQAB</Exponent>\r\n <Modulus>uzbtMdjXwkhvggQctl7TLg/YkM1UxHLqtj8zcntD/O/M+T/gCpMYRFjgHaM9+c1PwCFkG5yBw5VB0nxKUjoAnSo1K9PgGSHWUk4WRXtNrIRkUITQGQsU3GPLDHDzbu0w4+1v/UGE7POK5i3f64g70VdtwjQ3v7pa2soTWd/Mgah7WO33lJKC8RgM9HDo54874YFnFT+vgfP5wRYNHTb3UEITS/+qE4xooZtR0vzgWXymkb1f4MPFh5pm5S9dnAI5qRI2iqowYdpUitZAnnOPfR2lmQLeyH4D2wX6GycgnzFK5N6994jQl+Dn/qy8UbNUP647z5cl8KLfYtNZCg46ZQ==</Modulus>\r\n <P>4mF96uxly2vdKzwDdIGpe4rWzvSk9v/hu5shAoyy7CF0Cimjo+0irOaQOzZNfczp8ipjtQJoFFm/PovSr+sOn00V58bVTcf9YZZf7yDmWAYTO3rQPY9wc0oIm0q8ncpdhg3dkNqMuxg9Vzl5Y/G/foty9zcv3Ph2FVkc+ATOfRs=</P>\r\n <Q>07WUrxYBow0Blwpa4f5xi75z1bASQhrz+8qmQgX2JwUPyhQ7Ayt8snLDpngpuuvmtGZ7j3SaS0Ce+Y1rrlyb8rzqdijqOrwwpuGlrIHl79vwCkoUmb6Xmw+Grx5kCRwCwHW1nnvBDoPDIJyo+uHdsoBXcfRJRmOiGHPomUcvHn8=</Q>\r\n <DP>WRvxGbkF9MW3oF4WKhUj5opnNb2c9dERROyyWLOTdllQuPNdA5jDbnWvTm94n006xWUkLEsPNvuAyRj2zOJkthX8ymg87EoNlg1AI/u6T+nMRjx4ndLJe8gnjSElD6Npnuv0TCGLBdZrxtrLyqiNLT2s+lzRzVRL/uk9+u7BbQM=</DP>\r\n <DQ>uHYH/J3CA107u2yMT0ixij8BEnj9D5gIaaTiQ7iKBumEHmCOIm7rkVgpXIxqX7FXLGv20MGaBmNhoLI11pBeWJt99kIkA9Ug1ubYwXvU6q7JcU2msWa9FZ/ri/2Az+cWBrcI7fOJ/KmVhH67RQ0za2ojxuhASBJbk866JYM+bOU=</DQ>\r\n <InverseQ>O0mybCngn3qkItEfCxwOT0ayyye+ygJxZJ0sU9SncCfcREf/ecWAfpDjQNSUmOFph+JBUMkrgGYtGja7Ht976VW5m66pgAXUmIouAlO/R+J4cNHMGWUW42xrYfTxhYnsY5Yfbijy4O685lR/c1iXeg8ArGFblblniQEjLs7Tbb4=</InverseQ>\r\n <D>Km9lzmGvbjtLAzZ5Z6EQzyUKWrAgIbNGnm6u86kbHQ8h7/FZkCwNWRioHC+vUZsHE6696UBNbY68b8B6fC7nirhRexC4gBnaYaePhspPLeaIcnPYU4TegqIgGT7U/vTGmzNrqgUa4zbE6i3FzrZ/kJD3sQhzBoNwKp2ZS0reKRkrJyVZDVO0fRfHZLOS+d4uOb5XzngwFmmWcunlrPpCmG+mDUbQTR5Dd12x/qVI/LNgANJXdl4/A0ob9WA4D98agITkCyFbUXTHfZBLhTtCkNammAcCfPCV6HWFl52+I3VFP+SHfOZLS/Zwlc/fJ0BPVGi0izy+KvtRC3qsZtmPlQ==</D>\r\n</RSAParameters>");
Console.WriteLine(Convert.ToBase64String(cryptoServiceProvider.Encrypt(Encoding.Default.GetBytes(value), true)));
}
private static void Main()
{
try
{
Encrypt("Test");
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadLine();
}
This will output the following cipher text for ?Test? in Base64 encoding on the console.
DctjVLlXN61aMU4NWLJwz46c/t3UlwJ67yTBsSBXwltf9Wvi2JY0HT6kj0Ls3wvQTiFPB426Qkg7A3LejpcIdRcPWb7jZiBUnbAZveIcRPyi/I0qppOeBfleEQYwTmIcFZAuJ0P9N/8fTOQEJNJjCSQBTaf+gbMAFnz04lnsEFnk2XnwJfAk73B0dmb/PKdbCY5ijXwigk+6ftWZsKgRFWMY4cDCeyKibJMhwoGtVLq/Rc2vrCE3YbOPbEWnKW+v+DuJlOGJvWzGNTLT4rCQhhyvSI2SvV3Kni9hJbhM3tI9rgcnY7f/F0jpoUAPCsGEcHgSZAhSXYPCviuoxUySIw==
As you can see both cipher texts do not match. Can you please give me a hint which property I am not using correctly to get the same results in Delphi and .NET.
I also noted that the public exponent in Delphi differs from the one passed to the property of the RSA object when logging it to the console. May be this could be the difference?
Thank you in advance!
Regards,
Maik
Secondly, you use OAEP padding method in Delphi code, are you sure RSACryptoServiceProvider uses this method? The PKCS#1 v1.5 is a more used method (although less secure).
I cannot test if all these changes are sufficient. But the Delphi code can be :
uses
System.SysUtils, RSAObj, MiscObj;
procedure Encrypt(Value: string);
var
RSA: TRSAEncSign;
conv: TConvert;
begin
RSA := TRSAEncSign.Create;
conv := TConvert.Create(base64);
RSA.keyLength := kl2048;
RSA.encType := epkcs1_5;
RSA.outputFormat := base64;
RSA.modulus := Conv.KeyRSAOpenSSLToKeyTRSAEncSign('uzbtMdjXwkhvggQctl7TLg/YkM1UxHLqtj8zcntD/O/M+T/gCpMYRFjgHaM9+c1PwCFkG5yBw5VB0nxKUjoAnSo1K9PgGSHWUk4WRXtNrIRkUITQGQsU3GPLDHDzbu0w' +
'4+1v/UGE7POK5i3f64g70VdtwjQ3v7pa2soTWd/Mgah7WO33lJKC8RgM9HDo54874YFnFT+vgfP5wRYNHTb3UEITS/+qE4xooZtR0vzgWXymkb1f4MPFh5pm5S9dnAI5' +
'qRI2iqowYdpUitZAnnOPfR2lmQLeyH4D2wX6GycgnzFK5N6994jQl+Dn/qy8UbNUP647z5cl8KLfYtNZCg46ZQ==');
RSA.PublicExponent := Conv.KeyRSAOpenSSLToKeyTRSAEncSign('AQAB');
WriteLn(RSA.Encrypt(Value));
end;
begin
try
Encrypt('Test');
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
Tell me if the issue still remains.
Best regards,
Marion
Hi Marion,
In our component, we use SHA-256.
Hi Marion,
Hi Marion,
Hi Marion,
Hi Marion,
I did more tests also with another crypto library for .NET with the name "BouncyCastle Crypto". I think you have an issue with the public exponent in your implementation of RSA. I have generated the following key parameters and exported them in Base64 encoding.
Modulus: Tb4CdAMiMWpSzvuehXga4vL1hus2vf+rlJBwfOp8TRCnaPsQrjjJGruX1UFnF4pFijra6vRKR+dU02khPEGLXFNwwBoskhlXEY5kb3doC+iRvYQnasC/m0A53T/QAsh6oJKPK9pUdkNyhLXZH+qaN7qsSG+EisqQE13bO5NM/JR/2jXEzJTyhwjxYL7+p/UGeJ7pacq1eEFeazHz16nYGZM07o3Qw7ezX4CVjyCOMaR7TsSj1+OReWBSm2AMYeKrkWdV84TVhHoTEIASZqLRBbk6t8LlNHNX6IpOTklO9BpJeYrvRT01+wjoM33Bp9aPoTqfBbD7LFANILQKQ+EZgg==
Public exponent: BwAAAAAAIBAAQAAACAAAAAAEAAAAAAAAAAAAAAAAAAA=
Private exponent: s7BXdBqmHKK0HtpKBy1Rb6uLss7LZA+DxYa4z0L46PThG+FsCX6Xl8j/UyGXgnUGAwfzvKp5ioTnML4A+DMqKmXX/xqcNG5AiXLDGNwO3TCjD5rtwemg6faYCKmmiOIpuRJ+oEJ1mOltGtjRiX314YIDDP6P1m2kzlbbAkWJrMxHR4tlHrdFp9Cuw61m1clZ1KAaUCpqbVNfUOdPmsEPSU1Xn8QO3NyeWCTxcnBGHDKtmwuoknUjMeztWM0+IxBVJVmIXjpSluR11NW4m8P4HVjHDzdCdIm1/v7MYkpOfRviIuJsR8yfVEXqzuuzd437oTNkiPbWbXICElHyko1QbQ==
When I now try to construct an private key object for RSA with the BCCrypto library I receive an exception saying that the provided public exponent is even and the creation of the object fails.
As mentioned before I have also noticed that my public exponent generated in .NET (AQAB) is changed when providing it to your RSA library and logging it to the console in its Base64 representation (AQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=). It also makes no difference wether I use the Convert object or not.
Here is the code of my Delphi test application.
uses
System.SysUtils, RSAObj, MiscObj;
var
RSA: TRSAEncSign;
begin
try
RSA := TRSAEncSign.Create;
RSA.keyLength := kl2048;
RSA.encType := oaep;
RSA.outputFormat := base64;
RSA.modulus :=
'nHOjA+WQ8NgRJ1O2ZvbQE7h3RaxBNGCxwwudVvGcqjE4+bmhO9hE/2iX/uZEhTNDEEVS6OSm3aO/jEpjJ3iu+baZq16Zd3leAgNmvISlREbu25OaMA1sN/an9Hkrda5es9xcnRoCvPfv76'
+ 'WXFSaaag+mIE9vlZG7InR9kOdESNHXvaFkhAOW7lPquVv/jwsCtP/jXSOvRWSXjvSFJvoiP1i1MKd4imFg/TUk8LRQ1onehiyMs1719AH5rOjPr/lasTB0Do8Zc3NwEkj2+W2ylMZYH5KvQ1YkF6bc6sg40nq4hWgyZ3a9MmacPP3u4m9nbyO8WCPpcYY3uXwDn6tl4Q==';
RSA.PublicExponent := 'AQAB';
WriteLn('Modulus: ' + RSA.modulus);
WriteLn('Public Exponent: ' + RSA.PublicExponent);
except
on E: Exception do
WriteLn(E.ClassName, ': ', E.Message);
end;
Readln;
end.
And this is the console output.
Modulus: nHOjA+WQ8NgRJ1O2ZvbQE7h3RaxBNGCxwwudVvGcqjE4+bmhO9hE/2iX/uZEhTNDEEVS6OSm3aO/jEpjJ3iu+baZq16Zd3leAgNmvISlREbu25OaMA1sN/an9Hkrda5es9xcnRoCvPfv76WXFSaaag+mIE9vlZG7InR9kOdESNHXvaFkhAOW7lPquVv/jwsCtP/jXSOvRWSXjvSFJvoiP1i1MKd4imFg/TUk8LRQ1onehiyMs1719AH5rOjPr/lasTB0Do8Zc3NwEkj2+W2ylMZYH5KvQ1YkF6bc6sg40nq4hWgyZ3a9MmacPP3u4m9nbyO8WCPpcYY3uXwDn6tl4Q==
Public Exponent: AQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
I hope this helps for your further investigations.
Regards,
Maik
Hi Marion,
Hi Marion,