forked from loafle/openapi-generator-original
various enhancements to PSRSAEncryptionProvider (#10914)
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
/*
|
||||
* OpenAPI Petstore
|
||||
*
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
* Generated by: https://github.com/openapitools/openapi-generator.git
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -9,8 +17,17 @@ using System.Text;
|
||||
|
||||
namespace RSAEncryption
|
||||
{
|
||||
/// <summary>
|
||||
/// A RSA enccryption provider.
|
||||
/// </summary>
|
||||
public class RSAEncryptionProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the RSA provider from the PEM file.
|
||||
/// </summary>
|
||||
/// <param name="pemfile">PEM file.</param>
|
||||
/// <param name="keyPassPhrase">Key pass phrase.</param>
|
||||
/// <returns>Get an instance of RSACryptoServiceProvider.</returns>
|
||||
public static RSACryptoServiceProvider GetRSAProviderFromPemFile(String pemfile,SecureString keyPassPhrase = null)
|
||||
{
|
||||
const String pempubheader = "-----BEGIN PUBLIC KEY-----";
|
||||
@@ -41,6 +58,12 @@ namespace RSAEncryption
|
||||
return null ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the private key to bytes.
|
||||
/// </summary>
|
||||
/// <param name="instr">Private key.</param>
|
||||
/// <param name="keyPassPhrase">Key pass phrase.</param>
|
||||
/// <returns>The private key in the form of bytes.</returns>
|
||||
static byte[] ConvertPrivateKeyToBytes(String instr, SecureString keyPassPhrase = null)
|
||||
{
|
||||
const String pemprivheader = "-----BEGIN RSA PRIVATE KEY-----";
|
||||
@@ -69,16 +92,24 @@ namespace RSAEncryption
|
||||
|
||||
//-------- read PEM encryption info. lines and extract salt -----
|
||||
if (!str.ReadLine().StartsWith("Proc-Type: 4,ENCRYPTED"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String saltline = str.ReadLine();
|
||||
if (!saltline.StartsWith("DEK-Info: DES-EDE3-CBC,"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String saltstr = saltline.Substring(saltline.IndexOf(",") + 1).Trim();
|
||||
byte[] salt = new byte[saltstr.Length / 2];
|
||||
for (int i = 0; i < salt.Length; i++)
|
||||
{
|
||||
salt[i] = Convert.ToByte(saltstr.Substring(i * 2, 2), 16);
|
||||
if (!(str.ReadLine() == ""))
|
||||
}
|
||||
if (str.ReadLine() != "")
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//------ remaining b64 data is encrypted RSA key ----
|
||||
String encryptedstr = str.ReadToEnd();
|
||||
@@ -94,7 +125,9 @@ namespace RSAEncryption
|
||||
|
||||
byte[] deskey = GetEncryptedKey(salt, keyPassPhrase, 1, 2); // count=1 (for OpenSSL implementation); 2 iterations to get at least 24 bytes
|
||||
if (deskey == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//------ Decrypt the encrypted 3des-encrypted RSA private key ------
|
||||
byte[] rsakey = DecryptKey(binkey, deskey, salt); //OpenSSL uses salt value in PEM header also as 3DES IV
|
||||
@@ -102,9 +135,14 @@ namespace RSAEncryption
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decode the RSA private key.
|
||||
/// </summary>
|
||||
/// <param name="privkey">Private key.</param>
|
||||
/// <returns>An instance of RSACryptoServiceProvider.</returns>
|
||||
public static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
|
||||
{
|
||||
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
|
||||
byte[] bytesModules, bytesE, bytesD, bytesP, bytesQ, bytesDp, bytesDq, bytesIq;
|
||||
|
||||
// --------- Set up stream to decode the asn.1 encoded RSA private key ------
|
||||
MemoryStream mem = new MemoryStream(privkey);
|
||||
@@ -116,63 +154,76 @@ namespace RSAEncryption
|
||||
{
|
||||
twobytes = binr.ReadUInt16();
|
||||
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
|
||||
{
|
||||
binr.ReadByte(); //advance 1 byte
|
||||
}
|
||||
else if (twobytes == 0x8230)
|
||||
{
|
||||
binr.ReadInt16(); //advance 2 bytes
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
twobytes = binr.ReadUInt16();
|
||||
if (twobytes != 0x0102) //version number
|
||||
{
|
||||
return null;
|
||||
}
|
||||
bt = binr.ReadByte();
|
||||
if (bt != 0x00)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//------ all private key components are Integer sequences ----
|
||||
elems = GetIntegerSize(binr);
|
||||
MODULUS = binr.ReadBytes(elems);
|
||||
bytesModules = binr.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binr);
|
||||
E = binr.ReadBytes(elems);
|
||||
bytesE = binr.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binr);
|
||||
D = binr.ReadBytes(elems);
|
||||
bytesD = binr.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binr);
|
||||
P = binr.ReadBytes(elems);
|
||||
bytesP = binr.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binr);
|
||||
Q = binr.ReadBytes(elems);
|
||||
bytesQ = binr.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binr);
|
||||
DP = binr.ReadBytes(elems);
|
||||
bytesDp = binr.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binr);
|
||||
DQ = binr.ReadBytes(elems);
|
||||
bytesDq = binr.ReadBytes(elems);
|
||||
|
||||
elems = GetIntegerSize(binr);
|
||||
IQ = binr.ReadBytes(elems);
|
||||
bytesIq = binr.ReadBytes(elems);
|
||||
|
||||
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
|
||||
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
|
||||
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
|
||||
RSAParameters RSAparams = new RSAParameters();
|
||||
RSAparams.Modulus = MODULUS;
|
||||
RSAparams.Exponent = E;
|
||||
RSAparams.D = D;
|
||||
RSAparams.P = P;
|
||||
RSAparams.Q = Q;
|
||||
RSAparams.DP = DP;
|
||||
RSAparams.DQ = DQ;
|
||||
RSAparams.InverseQ = IQ;
|
||||
RSA.ImportParameters(RSAparams);
|
||||
return RSA;
|
||||
RSAparams.Modulus = bytesModules;
|
||||
RSAparams.Exponent = bytesE;
|
||||
RSAparams.D = bytesD;
|
||||
RSAparams.P = bytesP;
|
||||
RSAparams.Q = bytesQ;
|
||||
RSAparams.DP = bytesDp;
|
||||
RSAparams.DQ = bytesDq;
|
||||
RSAparams.InverseQ = bytesIq;
|
||||
rsa.ImportParameters(RSAparams);
|
||||
return rsa;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
finally { binr.Close(); }
|
||||
finally
|
||||
{
|
||||
binr.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetIntegerSize(BinaryReader binr)
|
||||
@@ -183,13 +234,16 @@ namespace RSAEncryption
|
||||
int count = 0;
|
||||
bt = binr.ReadByte();
|
||||
if (bt != 0x02) //expect integer
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
bt = binr.ReadByte();
|
||||
|
||||
if (bt == 0x81)
|
||||
{
|
||||
count = binr.ReadByte(); // data size in next byte
|
||||
else
|
||||
if (bt == 0x82)
|
||||
}
|
||||
else if (bt == 0x82)
|
||||
{
|
||||
highbyte = binr.ReadByte(); // data size in next 2 bytes
|
||||
lowbyte = binr.ReadByte();
|
||||
@@ -209,10 +263,18 @@ namespace RSAEncryption
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the encrypted key.
|
||||
/// </summary>
|
||||
/// <param name="salt">Random bytes to be added.</param>
|
||||
/// <param name="secpswd">Password.</param>
|
||||
/// <param name="count">Count.</param>
|
||||
/// <param name="miter">Miter.</param>
|
||||
/// <returns>Decrypted key.</returns>
|
||||
static byte[] GetEncryptedKey(byte[] salt, SecureString secpswd, int count, int miter)
|
||||
{
|
||||
IntPtr unmanagedPswd = IntPtr.Zero;
|
||||
int HASHLENGTH = 16; //MD5 bytes
|
||||
const int HASHLENGTH = 16; //MD5 bytes
|
||||
byte[] keymaterial = new byte[HASHLENGTH * miter]; //to store concatenated Mi hashed results
|
||||
|
||||
byte[] psbytes = new byte[secpswd.Length];
|
||||
@@ -234,7 +296,9 @@ namespace RSAEncryption
|
||||
{
|
||||
// ---- Now hash consecutively for count times ------
|
||||
if (j == 0)
|
||||
{
|
||||
result = data00; //initialize
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Copy(result, hashtarget, result.Length);
|
||||
@@ -243,7 +307,9 @@ namespace RSAEncryption
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
result = md5.ComputeHash(result);
|
||||
}
|
||||
Array.Copy(result, 0, keymaterial, j * HASHLENGTH, result.Length); //concatenate to keymaterial
|
||||
}
|
||||
byte[] deskey = new byte[24];
|
||||
@@ -257,6 +323,13 @@ namespace RSAEncryption
|
||||
return deskey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypt the key.
|
||||
/// </summary>
|
||||
/// <param name="chipherData">Cipher data.</param>
|
||||
/// <param name="desKey">Key to decrypt.</param>
|
||||
/// <param name="IV">Initialization vector.</param>
|
||||
/// <returns>Decrypted key.</returns>
|
||||
static byte[] DecryptKey(byte[] cipherData, byte[] desKey, byte[] IV)
|
||||
{
|
||||
MemoryStream memst = new MemoryStream();
|
||||
@@ -269,7 +342,8 @@ namespace RSAEncryption
|
||||
cs.Write(cipherData, 0, cipherData.Length);
|
||||
cs.Close();
|
||||
}
|
||||
catch (Exception){
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
byte[] decryptedData = memst.ToArray();
|
||||
|
||||
Reference in New Issue
Block a user