PDA

View Full Version : کلید RSA



behnia_k
سه شنبه 10 فروردین 1400, 10:24 صبح
با سلام

در صورتی که مقادیر زیر را برای یک کلید RSA داشته باشیم.



Public modulus [n]
B5B27BDE789A290F533EA72794CFE87112A228089F3F43D53A E9365E0C348557ADEE924D3E3C443FDB22B09FA3D51ABBACC9 B1E8C36264437979A62776E686CD

Public exponent [e]
010001

Private exponent [d]
2248B152C312E3987EAE9DBFBC3696B76F3AA5AF2ACD37316E D23E6DF4839C7D235D17B80A1CAFAD3ACA6CF877E0831134A2 9A4062A03C4E1A0C69A644A89A41


چگونه از روی آنها کلیدهای public و private را در #C تولید کنیم

the king
چهارشنبه 11 فروردین 1400, 10:25 صبح
با سلام

در صورتی که مقادیر زیر را برای یک کلید RSA داشته باشیم.



Public modulus [n]
B5B27BDE789A290F533EA72794CFE87112A228089F3F43D53A E9365E0C348557ADEE924D3E3C443FDB22B09FA3D51ABBACC9 B1E8C36264437979A62776E686CD

Public exponent [e]
010001

Private exponent [d]
2248B152C312E3987EAE9DBFBC3696B76F3AA5AF2ACD37316E D23E6DF4839C7D235D17B80A1CAFAD3ACA6CF877E0831134A2 9A4062A03C4E1A0C69A644A89A41


چگونه از روی آنها کلیدهای public و private را در #C تولید کنیم




درسته که داشتن این سه پارامتر n و e و d کافی است اما RSAParameters از یکسری پارامتر جانبی هم استفاده می کنه که بصورت خودکار محاسبه نمیشن.
کلید عمومی و خصوصی در RSAParameters نگهداری میشه و می توانید بر اساس n و e و d سایر پارامتر های RSAParameters رو محاسبه کنید.
برای محاسبه پارامتر هایی مثل P و Q و DP باید یکسری محاسبات انجام بشه که در کلاس MyRSA که ساختم و پیوست کردم بصورت خودکار انجام شده :

153184

153185

برای منبع محاسبات رجوع شود به :

https://stackoverflow.com/a/44441955

behnia_k
چهارشنبه 11 فروردین 1400, 11:20 صبح
درسته که داشتن این سه پارامتر n و e و d کافی است اما RSAParameters از یکسری پارامتر جانبی هم استفاده می کنه که بصورت خودکار محاسبه نمیشن.
کلید عمومی و خصوصی در RSAParameters نگهداری میشه و می توانید بر اساس n و e و d سایر پارامتر های RSAParameters رو محاسبه کنید.
برای محاسبه پارامتر هایی مثل P و Q و DP باید یکسری محاسبات انجام بشه که در کلاس MyRSA که ساختم و پیوست کردم بصورت خودکار انجام شده :

153184

153185

برای منبع محاسبات رجوع شود به :

https://stackoverflow.com/a/44441955

متشکرم.

یک تجربه BigInteger.Parse برای مبنای 16 جالب نیست اگر لازم دارید دوباره بنویسید.

آیا در مورد فرمت فایل های کلید RSA اطلاع دارید. لازم به ذکر است مطالبی پیدا کردم ولی هنوز نتواستم به یک نتیجه واضح برسم

the king
چهارشنبه 11 فروردین 1400, 13:35 عصر
یک تجربه BigInteger.Parse برای مبنای 16 جالب نیست اگر لازم دارید دوباره بنویسید.

متوجه نشدم چی جالب نیست یا چی لازم هست.
BigInteger.Parse برای مقدار دهی BigInteger مناسبه اما RSACryptoServiceProvider و RSAParameters بر اساس نوع داده []byte عمل می کنند، نه BigInteger.
بخاطر اینکه منبع داده شون []byte ئه، تبدیل رشته مبنای 16 به BigInteger در این مورد استفاده ای نداره.

barnamenevisjavan
چهارشنبه 11 فروردین 1400, 14:26 عصر
من بصورت زیر کلیدهای عمومی و خصوصی رو ایجاد میکنم
public class RSAKey
{
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
}


/// <summary>
/// This method generates RSA public and private keys
/// KeySize is measured in bits. 1024 is the default, 2048 is better, 4096 is more robust but takes a fair bit longer to generate.
/// </summary>
/// <returns></returns>
public static RSAKey GenerateRSAKey(int keySize = 1024)
{
using (var rsa = new RSACryptoServiceProvider(keySize))
{
return new RSAKey { PublicKey = rsa.ToXmlString(false), PrivateKey = rsa.ToXmlString(true) };
}
}

behnia_k
پنج شنبه 12 فروردین 1400, 20:17 عصر
متوجه نشدم چی جالب نیست یا چی لازم هست.
BigInteger.Parse برای مقدار دهی BigInteger مناسبه اما RSACryptoServiceProvider و RSAParameters بر اساس نوع داده []byte عمل می کنند، نه BigInteger.
بخاطر اینکه منبع داده شون []byte ئه، تبدیل رشته مبنای 16 به BigInteger در این مورد استفاده ای نداره.

منظورم تبدیل رشته های در مبنای 16 به
BigInteger هستش که هنگام تیدیل رشتخ هایی که اولین رقم سمت چپ آن از 7 بزرگتر باشد عدد را منقی در نظر میگیرد مثلا "C" برابر 12 نمی شود (امکان نابلد بودن من هست).

behnia_k
پنج شنبه 12 فروردین 1400, 20:21 عصر
من بصورت زیر کلیدهای عمومی و خصوصی رو ایجاد میکنم
public class RSAKey
{
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
}


/// <summary>
/// This method generates RSA public and private keys
/// KeySize is measured in bits. 1024 is the default, 2048 is better, 4096 is more robust but takes a fair bit longer to generate.
/// </summary>
/// <returns></returns>
public static RSAKey GenerateRSAKey(int keySize = 1024)
{
using (var rsa = new RSACryptoServiceProvider(keySize))
{
return new RSAKey { PublicKey = rsa.ToXmlString(false), PrivateKey = rsa.ToXmlString(true) };
}
}


متشکرم
منظور من گرفتن خروجی و یا ورودی کلید با فرمت pem هست. که ظاهرا انواع مختلف دارد.
فرمت XML هم هست ولی ظاهرا فرمت XML ای که خارج از محیط #C استفاده می شود با داخل محیط #C تفاوت دارد.
البته هنوز باید روی این موضوع کار کنم.

the king
پنج شنبه 12 فروردین 1400, 22:17 عصر
منظورم تبدیل رشته های در مبنای 16 به
BigInteger
هستش که هنگام تیدیل رشتخ هایی که اولین رقم سمت چپ آن از 7 بزرگتر باشد عدد را منقی در نظر میگیرد مثلا "C" برابر 12 نمی شود (امکان نابلد بودن من هست).
متاسفانه System.Numeric.BigInteger داده ورودی رو علامت دار در نظر میگیره، این رو نمیشه کاری کرد.
اما میدونیم داخل کلاسش یک متد سازنده private داره که []uint قبول می کنه (که چون private ئه در حالت عادی بهش دسترسی نداریم)
و میدونیم خود کلاسش هم عدد رو در یک فیلد private uint[] _data نگه میداره که مستقیما از همون متد سازنده داده میگیره.
پس میتونیم با کمک System.Reflection از اون متد سازنده private استفاده کنیم و داده بدون علامت رو بزور داخل شیء BigInteger تزریق کنیم:

using System.Numerics;
using System.Reflection;

private static BigInteger HexToBigInteger( string hex)
{
if ( hex.Trim( '0').Length == 0)
{
return BigInteger.Zero;
}
hex = '0' + hex.TrimStart( '0');
hex = hex.PadLeft( ( ( hex.Length + 7) / 8) * 8, '0');
var data = new uint[hex.Length / 8];
var pos = data.Length - 1;
for ( var index = 0; index < hex.Length; index += 8, pos--)
{
data[pos] = Convert.ToUInt32( hex.Substring( index, 8), 16);
}
var constructorInfo = typeof( BigInteger).GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof( int), typeof( uint[]) }, null);
return (BigInteger) constructorInfo.Invoke( new object[] { 1, data });
}


مثلا :

var hex = "FF";
var n1 = BigInteger.Parse( hex, System.Globalization. NumberStyles.HexNumber);
var n2 = HexToBigInteger( hex);
MessageBox.Show( "n1=" + n1 + Environment.NewLine + "n2=" + n2);



var hex = "C23B56789AE34";
var n1 = BigInteger.Parse( hex, System.Globalization. NumberStyles.HexNumber);
var n2 = HexToBigInteger( hex);
MessageBox.Show( "n1=" + n1 + Environment.NewLine + "n2=" + n2);

barnamenevisjavan
جمعه 13 فروردین 1400, 10:08 صبح
متشکرم
منظور من گرفتن خروجی و یا ورودی کلید با فرمت pem هست. که ظاهرا انواع مختلف دارد.
فرمت XML هم هست ولی ظاهرا فرمت XML ای که خارج از محیط #C استفاده می شود با داخل محیط #C تفاوت دارد.
البته هنوز باید روی این موضوع کار کنم.
از این دستور برای خروجی گرفتن کلید خصوصی استفاده کنید
public static void ExportPrivateKeyToFile(string path, string privateKey, string password, string symmetricSalt = null)
{
if (string.IsNullOrEmpty(symmetricSalt))
{
symmetricSalt = "salt";
}


var salt = Encoding.UTF8.GetBytes(symmetricSalt);
using (var cypher = new AesManaged())
{
var pdb = new Rfc2898DeriveBytes(password, salt);
var key = pdb.GetBytes(cypher.KeySize / 8);
var iv = pdb.GetBytes(cypher.BlockSize / 8);


using (var encryptor = cypher.CreateEncryptor(key, iv))
using (var fsEncrypt = new FileStream(path, FileMode.Create))
using (var csEncrypt = new CryptoStream(fsEncrypt, encryptor, CryptoStreamMode.Write))
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(privateKey);
}
}
}

behnia_k
شنبه 14 فروردین 1400, 07:54 صبح
متاسفانه System.Numeric.BigInteger داده ورودی رو علامت دار در نظر میگیره، این رو نمیشه کاری کرد.
اما میدونیم داخل کلاسش یک متد سازنده private داره که []uint قبول می کنه (که چون private ئه در حالت عادی بهش دسترسی نداریم)
و میدونیم خود کلاسش هم عدد رو در یک فیلد private uint[] _data نگه میداره که مستقیما از همون متد سازنده داده میگیره.
پس میتونیم با کمک System.Reflection از اون متد سازنده private استفاده کنیم و داده بدون علامت رو بزور داخل شیء BigInteger تزریق کنیم:


با تشکر من هم تا حدودی متوجه این موضوع شدم. برای رفع این مشکل من هنگام استفاده از متد BigInteger.Parse به سمت چپ داده ورودی کاراکتر '0' را اضافه کردم ظاهرا جواب درست است نظر شما چیست

the king
شنبه 14 فروردین 1400, 08:41 صبح
با تشکر من هم تا حدودی متوجه این موضوع شدم. برای رفع این مشکل من هنگام استفاده از متد BigInteger.Parse به سمت چپ داده ورودی کاراکتر '0' را اضافه کردم ظاهرا جواب درست است نظر شما چیست
بله. قطعا جواب میده.