|
@@ -10,63 +10,170 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper
|
|
|
{
|
|
|
public static class RsaHelper
|
|
|
{
|
|
|
- /// <summary>
|
|
|
- /// 从本地文件中读取用来签发 Token 的 RSA Key
|
|
|
- /// </summary>
|
|
|
- /// <param name="filePath">存放密钥的文件夹路径</param>
|
|
|
- /// <param name="withPrivate"></param>
|
|
|
- /// <param name="keyParameters"></param>
|
|
|
- /// <returns></returns>
|
|
|
- public static bool TryGetKeyParameters(string filePath, bool withPrivate, out RSAParameters keyParameters)
|
|
|
+ public static string RSASign(string data, string privateKeyPem)
|
|
|
{
|
|
|
- string filename = withPrivate ? "private.pem" : "public.pem";
|
|
|
- filePath = Path.Combine(filePath, filename);
|
|
|
- keyParameters = default(RSAParameters);
|
|
|
- if (File.Exists(filePath) == false) return false;
|
|
|
- // keyParameters = JsonConvert.DeserializeObject<RsaParameterStorage>(File.ReadAllText(filePath)).Map().To<RSAParameters>();
|
|
|
- return true;
|
|
|
+ RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPem);
|
|
|
+ byte[] dataBytes = Encoding.UTF8.GetBytes(data);
|
|
|
+ byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");
|
|
|
+ return Convert.ToBase64String(signatureBytes);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static byte[] GetPem(string type, byte[] data)
|
|
|
+ {
|
|
|
+ string pem = Encoding.UTF8.GetString(data);
|
|
|
+ string header = String.Format("-----BEGIN {0}-----\\n", type);
|
|
|
+ string footer = String.Format("-----END {0}-----", type);
|
|
|
+ int start = pem.IndexOf(header) + header.Length;
|
|
|
+ int end = pem.IndexOf(footer, start);
|
|
|
+ string base64 = pem.Substring(start, (end - start));
|
|
|
+ return Convert.FromBase64String(base64);
|
|
|
+ }
|
|
|
+ public static string LoadCertificateFileToSting (string filename) {
|
|
|
+ FileStream fs = System.IO.File.OpenRead(filename);
|
|
|
+ byte[] data = new byte[fs.Length];
|
|
|
+ byte[] res = null;
|
|
|
+ fs.Read(data, 0, data.Length);
|
|
|
+ if (data[0] != 0x30)
|
|
|
+ {
|
|
|
+ res = GetPem("RSA PRIVATE KEY", data);
|
|
|
+ }
|
|
|
+ return res.ToJson();
|
|
|
+ }
|
|
|
+ public static RSACryptoServiceProvider LoadCertificateFile(string filename)
|
|
|
+ {
|
|
|
+ FileStream fs = System.IO.File.OpenRead(filename);
|
|
|
+ byte[] data = new byte[fs.Length];
|
|
|
+ byte[] res = null;
|
|
|
+ fs.Read(data, 0, data.Length);
|
|
|
+ if (data[0] != 0x30)
|
|
|
+ {
|
|
|
+ res = GetPem("RSA PRIVATE KEY", data);
|
|
|
+ }
|
|
|
+ try
|
|
|
+ {
|
|
|
+ string ss= res.ToJson();
|
|
|
+ RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(res);
|
|
|
+ string s = rsa.ToString();
|
|
|
+ return rsa;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ }
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// 生成并保存 RSA 公钥与私钥
|
|
|
- /// </summary>
|
|
|
- /// <param name="filePath">存放密钥的文件夹路径</param>
|
|
|
- /// <returns></returns>
|
|
|
- public static RSAParameters GenerateAndSaveKey(string filePath)
|
|
|
+ private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
|
|
|
{
|
|
|
- RSAParameters publicKeys, privateKeys;
|
|
|
- using (var rsa = new RSACryptoServiceProvider(2048))
|
|
|
+ byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
|
|
|
+
|
|
|
+ // --------- Set up stream to decode the asn.1 encoded RSA private key ------
|
|
|
+ MemoryStream mem = new MemoryStream(privkey);
|
|
|
+ BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
|
|
|
+ byte bt = 0;
|
|
|
+ ushort twobytes = 0;
|
|
|
+ int elems = 0;
|
|
|
+ try
|
|
|
{
|
|
|
- try
|
|
|
- {
|
|
|
- privateKeys = rsa.ExportParameters(true);
|
|
|
- publicKeys = rsa.ExportParameters(false);
|
|
|
- }
|
|
|
- finally
|
|
|
- {
|
|
|
- rsa.PersistKeyInCsp = false;
|
|
|
- }
|
|
|
+ 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);
|
|
|
+
|
|
|
+ elems = GetIntegerSize(binr);
|
|
|
+ E = binr.ReadBytes(elems);
|
|
|
+
|
|
|
+ elems = GetIntegerSize(binr);
|
|
|
+ D = binr.ReadBytes(elems);
|
|
|
+
|
|
|
+ elems = GetIntegerSize(binr);
|
|
|
+ P = binr.ReadBytes(elems);
|
|
|
+
|
|
|
+ elems = GetIntegerSize(binr);
|
|
|
+ Q = binr.ReadBytes(elems);
|
|
|
+
|
|
|
+ elems = GetIntegerSize(binr);
|
|
|
+ DP = binr.ReadBytes(elems);
|
|
|
+
|
|
|
+ elems = GetIntegerSize(binr);
|
|
|
+ DQ = binr.ReadBytes(elems);
|
|
|
+
|
|
|
+ elems = GetIntegerSize(binr);
|
|
|
+ IQ = binr.ReadBytes(elems);
|
|
|
+
|
|
|
+
|
|
|
+ // ------- create RSACryptoServiceProvider instance and initialize with public key -----
|
|
|
+ CspParameters CspParameters = new CspParameters();
|
|
|
+ CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
|
|
|
+ RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ binr.Close();
|
|
|
}
|
|
|
- File.WriteAllText(Path.Combine(filePath, "private.pem"), privateKeys.ToJsonString());
|
|
|
- File.WriteAllText(Path.Combine(filePath, "public.pem"), publicKeys.ToJsonString());
|
|
|
- return privateKeys;
|
|
|
}
|
|
|
|
|
|
- static string ToJsonString(this RSAParameters parameters)
|
|
|
+ private static int GetIntegerSize(BinaryReader binr)
|
|
|
{
|
|
|
- // var content = MessagePackHelper.ByteToObject<RsaParameterStorage>(MessagePackHelper.ObjectToByte(parameters));
|
|
|
- return JsonConvert.SerializeObject(parameters);
|
|
|
+ byte bt = 0;
|
|
|
+ byte lowbyte = 0x00;
|
|
|
+ byte highbyte = 0x00;
|
|
|
+ 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)
|
|
|
+ {
|
|
|
+ highbyte = binr.ReadByte(); // data size in next 2 bytes
|
|
|
+ lowbyte = binr.ReadByte();
|
|
|
+ byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
|
|
|
+ count = BitConverter.ToInt32(modint, 0);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ count = bt; // we already have the data size
|
|
|
+ }
|
|
|
+
|
|
|
+ while (binr.ReadByte() == 0x00)
|
|
|
+ { //remove high order zeros in data
|
|
|
+ count -= 1;
|
|
|
+ }
|
|
|
+ binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
|
|
|
+ return count;
|
|
|
}
|
|
|
- //class RsaParameterStorage
|
|
|
- //{
|
|
|
- // public byte[] D { get; set; }
|
|
|
- // public byte[] DP { get; set; }
|
|
|
- // public byte[] DQ { get; set; }
|
|
|
- // public byte[] Exponent { get; set; }
|
|
|
- // public byte[] InverseQ { get; set; }
|
|
|
- // public byte[] Modulus { get; set; }
|
|
|
- // public byte[] P { get; set; }
|
|
|
- // public byte[] Q { get; set; }
|
|
|
- //}
|
|
|
}
|
|
|
}
|