问题
I have public key in XML that created in C# the format is:
<Modulus>rYDd94biRAJ1P6j68xjARl......and so on</Modulus>
<Exponent>A**B</Exponent>
I want to create this key in Javascript, and encrypt string with it, how can I do it?
Thanks,
回答1:
After so many hours researching, testing, giving up, researching again, etc., for a solution on RSA interoperability for .NET and Javascript, I have found this library:
http://www.jocys.com/Common/JsClasses/Documents/
Their classes have the same working code as the RSACryptoServiceProvider on the server.
What you have to do:
Download the source code from their Github : https://github.com/JocysCom/JsClasses/archive/master.zip
Rename the files from *.debug.js to *.js. See the list of files below, on (3).
Add the required files to your html page
<script type="text/javascript" src="js/System.js"></script> <script type="text/javascript" src="js/System.IO.js"></script> <script type="text/javascript" src="js/System.Text.js"></script> <script type="text/javascript" src="js/System.Convert.js"></script> <script type="text/javascript" src="js/System.BigInt.js"></script> <script type="text/javascript" src="js/System.BitConverter.js"></script> <script type="text/javascript" src="js/System.Security.Cryptography.js"></script> <script type="text/javascript" src="js/System.Security.Cryptography.SHA1.js"></script> <script type="text/javascript" src="js/System.Security.Cryptography.HMACSHA1.js"></script> <script type="text/javascript" src="js/System.Security.Cryptography.RSA.js"></script>
Add this javascript code to encrypt your text:
function RsaEncrypt() { //a public key generated from their sample. //your should generate yours and stamp it here. var xmlParams = "<RSAKeyValue>" + "<Modulus>pxtmFnrGI6Sb8ziyY+NRUDuQ4b/ETw5WabQ4daFQqzsCEr/6J/LLBU/2D5mO5/Wu5U/Rya1E55aYFZeaZMNqAw==</Modulus>" + "<Exponent>AQAB</Exponent>" + "<P>2TsVXWPEvDIJv/gd2rX9k0UOyXuaYgoAchIH6vUicis=</P>" + "<Q>xO4+OYREQfqYRQK7y73+RaUG0IxobT0OQ0c+Ok2hc4k=</Q>" + "<DP>K7/xgpiIU9rECeyfnp/OjS14V+3T3vDivBaTj6eFI3c=</DP>" + "<DQ>K4N9ClZ4gp+tn6oP9t//XEIvtEsiE+kmyqTmUhmvMAk=</DQ>" + "<InverseQ>p7o4BOlKZQZ693R1ViZ66y5gTjUkNNTd2za7/1YGBCs=</InverseQ>" + "<D>XZqFVrYy4qhECruJgVZFp/GVuD5Y0gev88nVjl5r911QT+I8vgJSklTso7jTlpMtf2oe7UZ0WRWEtgPS3tZn4Q==</D>" + "</RSAKeyValue>"; var rsa = new System.Security.Cryptography.RSACryptoServiceProvider(); rsa.FromXmlString(xmlParams); // Encrypt var decryptedBytes = System.Text.Encoding.UTF8.GetBytes(text); var doOaepPadding = true; var encryptedBytes = rsa.Encrypt(decryptedBytes, doOaepPadding); var encryptedString = System.Convert.ToBase64String(encryptedBytes); return encryptedString; }
Look for documentation (link above) on how to generate the private and public keys. The code is quite the same as you would manually write .NET on server.
You can also check their test page
回答2:
Also you can save public key in PEM format in C#:
private static string ExportPublicKey(RSACryptoServiceProvider csp)
{
var parameters = csp.ExportParameters(false);
using (var stream = new MemoryStream())
{
var writer = new BinaryWriter(stream);
writer.Write((byte)0x30); // SEQUENCE
using (var innerStream = new MemoryStream())
{
var innerWriter = new BinaryWriter(innerStream);
EncodeIntegerBigEndian(innerWriter, new byte[] { 0x00 }); // Version
EncodeIntegerBigEndian(innerWriter, parameters.Modulus);
EncodeIntegerBigEndian(innerWriter, parameters.Exponent);
EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.D
EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.P
EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.Q
EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.DP
EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.DQ
EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.InverseQ
var length = (int)innerStream.Length;
EncodeLength(writer, length);
writer.Write(innerStream.GetBuffer(), 0, length);
}
char[] base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray();
StringBuilder res = new StringBuilder();
res.AppendLine("-----BEGIN RSA PUBLIC KEY-----");
for (int i = 0; i < base64.Length; i += 64)
{
int l = Math.Min(64, base64.Length - i);
for (int j = 0; j < l; j++) res.Append(base64[i + j]);
res.AppendLine();
}
res.AppendLine("-----END RSA PUBLIC KEY-----");
return res.ToString();
}
}
private static void EncodeIntegerBigEndian(BinaryWriter stream, byte[] value, bool forceUnsigned = true)
{
stream.Write((byte)0x02); // INTEGER
var prefixZeros = 0;
for (var i = 0; i < value.Length; i++)
{
if (value[i] != 0) break;
prefixZeros++;
}
if (value.Length - prefixZeros == 0)
{
EncodeLength(stream, 1);
stream.Write((byte)0);
}
else
{
if (forceUnsigned && value[prefixZeros] > 0x7f)
{
// Add a prefix zero to force unsigned if the MSB is 1
EncodeLength(stream, value.Length - prefixZeros + 1);
stream.Write((byte)0);
}
else
{
EncodeLength(stream, value.Length - prefixZeros);
}
for (var i = prefixZeros; i < value.Length; i++)
{
stream.Write(value[i]);
}
}
}
private static void EncodeLength(BinaryWriter stream, int length)
{
if (length < 0) throw new ArgumentOutOfRangeException("length", "Length must be non-negative");
if (length < 0x80)
{
// Short form
stream.Write((byte)length);
}
else
{
// Long form
var temp = length;
var bytesRequired = 0;
while (temp > 0)
{
temp >>= 8;
bytesRequired++;
}
stream.Write((byte)(bytesRequired | 0x80));
for (var i = bytesRequired - 1; i >= 0; i--)
{
stream.Write((byte)(length >> (8 * i) & 0xff));
}
}
}
来源:https://stackoverflow.com/questions/14037204/import-net-public-xml-key-to-javascript-in-rsa