Atom Лента - Форум КриптоПро - Тема:разбор запроса на сертификат и получение открытого ключа - 10Форум КриптоПро - Atom Лентаurn:https:--www-cryptopro-ru:AtomLenta:ForumKriptoPro:Tema:razborzaprosanasertifikatipoluchenieotkrytogokljucha-10:1Copyright 2024 Форум КриптоПро2024-03-28T11:36:00Zhttps://www.cryptopro.ru/forum2/Images/YAFLogo.pngForum Adminhttps://www.cryptopro.ruforum@cryptopro.ruZloy Strelokhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=24537&name=Zloy StrelokZloy Strelokhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=24537&name=Zloy Streloktwo_oceanshttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=36490&name=two_oceansZloy Strelokhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=24537&name=Zloy StrelokYetAnotherForum.NETurn:https:--www-cryptopro-ru:ftPosts:st1:meid96909:1разбор запроса на сертификат и получение открытого ключа<table class="content postContainer_Alt" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: two_oceans <a href="/forum2/default.aspx?g=posts&m=96852#post96852"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>Вроде все так на первый взгляд, с темой на которую ссылка согласуется, хотя не проверял соответствуют ли 1 и 4 значениям X509_CERT и X509_CERT_REQUEST_TO_BE_SIGNED и правильные ли флаги. В закомментированном участке нет еще одного декодирования и тип кажется не исправлен, скопирован с декодирования выше. В принципе можно просто проверить результат CryptDecodeObject: если false вывести результат GetLastError() на консоль, если true выполнить закомментированные действия. По коду ошибки будет яснее что не так при декодировании.<br /><br />Что бросилось в глаза: 1. в общем случае в pem файле могут быть и посторонние данные, не только запрос. Желательно не читать все целиком, а выделить только содержимое между органичителями запроса. А вот если ограничителей нет - то декодировать все.<br />2. зачем данные полученной структуры из шага 1 в getBytes куда-то копировать и преобразовать тип? Это лишний шанс испортить данные. Не проще просто сделать второе объявление CryptDecodeObject2, в котором третьим входным параметром сразу будет IntPtr pbEncoded и передать указатель на полученную структуру (pvStructInfo) напрямую. Размер уже получаете как SizeOf(CERT_SIGNED_CONTENT_INFO).</div></div><br /><br />Спасибо большое! Не ожидал получить такой подробный и развернутый ответ =) Попробую применить советы.</td></tr></table>2018-11-06T10:14:48+03:002018-11-06T10:14:48+03:00Zloy Strelok<table class="content postContainer_Alt" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: two_oceans <a href="/forum2/default.aspx?g=posts&m=96852#post96852"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>Вроде все так на первый взгляд, с темой на которую ссылка согласуется, хотя не проверял соответствуют ли 1 и 4 значениям X509_CERT и X509_CERT_REQUEST_TO_BE_SIGNED и правильные ли флаги. В закомментированном участке нет еще одного декодирования и тип кажется не исправлен, скопирован с декодирования выше. В принципе можно просто проверить результат CryptDecodeObject: если false вывести результат GetLastError() на консоль, если true выполнить закомментированные действия. По коду ошибки будет яснее что не так при декодировании.<br /><br />Что бросилось в глаза: 1. в общем случае в pem файле могут быть и посторонние данные, не только запрос. Желательно не читать все целиком, а выделить только содержимое между органичителями запроса. А вот если ограничителей нет - то декодировать все.<br />2. зачем данные полученной структуры из шага 1 в getBytes куда-то копировать и преобразовать тип? Это лишний шанс испортить данные. Не проще просто сделать второе объявление CryptDecodeObject2, в котором третьим входным параметром сразу будет IntPtr pbEncoded и передать указатель на полученную структуру (pvStructInfo) напрямую. Размер уже получаете как SizeOf(CERT_SIGNED_CONTENT_INFO).</div></div><br /><br />Спасибо большое! Не ожидал получить такой подробный и развернутый ответ =) Попробую применить советы.</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid96852:1разбор запроса на сертификат и получение открытого ключа<table class="content postContainer" width="100%"><tr><td>Вроде все так на первый взгляд, с темой на которую ссылка согласуется, хотя не проверял соответствуют ли 1 и 4 значениям X509_CERT и X509_CERT_REQUEST_TO_BE_SIGNED и правильные ли флаги. В закомментированном участке нет еще одного декодирования и тип кажется не исправлен, скопирован с декодирования выше. В принципе можно просто проверить результат CryptDecodeObject: если false вывести результат GetLastError() на консоль, если true выполнить закомментированные действия. По коду ошибки будет яснее что не так при декодировании.<br /><br />Что бросилось в глаза: 1. в общем случае в pem файле могут быть и посторонние данные, не только запрос. Желательно не читать все целиком, а выделить только содержимое между органичителями запроса. А вот если ограничителей нет - то декодировать все.<br />2. зачем данные полученной структуры из шага 1 в getBytes куда-то копировать и преобразовать тип? Это лишний шанс испортить данные. Не проще просто сделать второе объявление CryptDecodeObject2, в котором третьим входным параметром сразу будет IntPtr pbEncoded и передать указатель на полученную структуру (pvStructInfo) напрямую. Размер уже получаете как SizeOf(CERT_SIGNED_CONTENT_INFO).</td></tr></table>2018-11-02T12:57:11+03:002018-11-02T12:57:11+03:00two_oceans<table class="content postContainer" width="100%"><tr><td>Вроде все так на первый взгляд, с темой на которую ссылка согласуется, хотя не проверял соответствуют ли 1 и 4 значениям X509_CERT и X509_CERT_REQUEST_TO_BE_SIGNED и правильные ли флаги. В закомментированном участке нет еще одного декодирования и тип кажется не исправлен, скопирован с декодирования выше. В принципе можно просто проверить результат CryptDecodeObject: если false вывести результат GetLastError() на консоль, если true выполнить закомментированные действия. По коду ошибки будет яснее что не так при декодировании.<br /><br />Что бросилось в глаза: 1. в общем случае в pem файле могут быть и посторонние данные, не только запрос. Желательно не читать все целиком, а выделить только содержимое между органичителями запроса. А вот если ограничителей нет - то декодировать все.<br />2. зачем данные полученной структуры из шага 1 в getBytes куда-то копировать и преобразовать тип? Это лишний шанс испортить данные. Не проще просто сделать второе объявление CryptDecodeObject2, в котором третьим входным параметром сразу будет IntPtr pbEncoded и передать указатель на полученную структуру (pvStructInfo) напрямую. Размер уже получаете как SizeOf(CERT_SIGNED_CONTENT_INFO).</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid96813:1разбор запроса на сертификат и получение открытого ключа<table class="content postContainer_Alt" width="100%"><tr><td>Добрый день. Пытаюсь на c# через P/Invoke разобрать запрос на сертификат и в итоге получить открытый ключ. По описанию в данной теме (https://www.cryptopro.ru/CryptoPro/forum/view.asp?q=1085), нужно дважды вызвать CryptDecodeObject - сперва получить структуру CERT_SIGNED_CONTENT а потом из нее получить CERT_REQUEST_INFO. Структуру CERT_SIGNED_CONTENT вроде удалось получить, а вот когда проделываю decode для нее, то указатель pcbStructInfo2 остается 0. Может быть я неправильно подаю полученную структуру на вход к CryptDecodeObject? Подскажите, пожалуйста, знающие люди!<br /><br />Результат в консоли и код прилагаю:<br /><br /><img src="https://cdn1.savepice.ru/uploads/2018/11/1/d49447175dd192a1dccb19358395f644-full.png" alt="результат в консоли" title="результат в консоли" class="UserPostedImage" style="max-width:200px;max-height:200px" /><br /><br /> <div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-csharp">public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
uint pcbStructInfo = 0;
byte[] raw = Convert.FromBase64String(File.ReadAllText("request.pem"));
CryptDecodeObject(65537,1,raw,raw.Length,0x8,IntPtr.Zero, ref pcbStructInfo);
Console.WriteLine("pcbStructInfo: " + pcbStructInfo);
IntPtr pvStructInfo = Marshal.AllocHGlobal((IntPtr)pcbStructInfo);
Console.WriteLine("pvStructInfo: " + pvStructInfo);
CryptDecodeObject(65537,1,raw,raw.Length,0x8,pvStructInfo, ref pcbStructInfo);
CERT_SIGNED_CONTENT_INFO str = new CERT_SIGNED_CONTENT_INFO();
str = Marshal.PtrToStructure<CERT_SIGNED_CONTENT_INFO>(pvStructInfo);
Console.WriteLine("str.SignatureAlgorithm.pszObjId: " + str.SignatureAlgorithm.pszObjId);
byte[] raw2 = getBytes(str);
uint pcbStructInfo2 = 0;
CryptDecodeObject(65537,4,raw2,raw2.Length,0x8,IntPtr.Zero, ref pcbStructInfo2);
Console.WriteLine("pcbStructInfo2: " + pcbStructInfo2);
/*
IntPtr pvStructInfo2 = Marshal.AllocHGlobal((IntPtr)pcbStructInfo2);
Console.WriteLine(pvStructInfo2);
CERT_REQUEST_INFO str2 = new CERT_REQUEST_INFO();
str = Marshal.PtrToStructure<CERT_SIGNED_CONTENT_INFO>(pvStructInfo2);
Console.WriteLine(str2.SubjectPublicKeyInfo.PublicKey.ToString());
*/
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
static byte[] getBytes(CERT_SIGNED_CONTENT_INFO str)
{
int size = Marshal.SizeOf(str);
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(str, ptr, false);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
[DllImport("crypt32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern Boolean CryptDecodeObject(
UInt32 dwCertEncodingType,
UInt32 lpszStructType,
byte[] pbEncoded,
Int32 cbEncoded,
UInt32 dwFlags,
IntPtr pvStructInfo,
ref UInt32 pcbStructInfo
);
public struct CERT_SIGNED_CONTENT_INFO {
public CRYPTOAPI_BLOB ToBeSigned;
public CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
public CRYPT_BIT_BLOB Signature;
}
public struct CRYPTOAPI_BLOB {
public UInt32 cbData;
public IntPtr pbData;
}
public struct CRYPT_ALGORITHM_IDENTIFIER {
[MarshalAs(UnmanagedType.LPStr)]
public String pszObjId;
public CRYPTOAPI_BLOB Parameters;
}
public struct CRYPT_BIT_BLOB {
public UInt32 cbData;
public IntPtr pbData;
public UInt32 cUnusedBits;
}
public struct CERT_REQUEST_INFO {
public uint dwVersion;
public CRYPTOAPI_BLOB Subject;
public CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo;
public uint cAttribute;
public CRYPT_ATTRIBUTE rgAttribute;
}
public struct CERT_PUBLIC_KEY_INFO {
public CRYPT_ALGORITHM_IDENTIFIER Algorithm;
public CRYPT_BIT_BLOB PublicKey;
}
public struct CRYPT_ATTRIBUTE {
public string pszObjId;
public UInt32 cValue;
public CRYPTOAPI_BLOB rgValue;
}</code></pre>
</div></div></td></tr></table>2018-11-01T11:21:19+03:002018-11-01T11:21:19+03:00Zloy Strelok<table class="content postContainer_Alt" width="100%"><tr><td>Добрый день. Пытаюсь на c# через P/Invoke разобрать запрос на сертификат и в итоге получить открытый ключ. По описанию в данной теме (https://www.cryptopro.ru/CryptoPro/forum/view.asp?q=1085), нужно дважды вызвать CryptDecodeObject - сперва получить структуру CERT_SIGNED_CONTENT а потом из нее получить CERT_REQUEST_INFO. Структуру CERT_SIGNED_CONTENT вроде удалось получить, а вот когда проделываю decode для нее, то указатель pcbStructInfo2 остается 0. Может быть я неправильно подаю полученную структуру на вход к CryptDecodeObject? Подскажите, пожалуйста, знающие люди!<br /><br />Результат в консоли и код прилагаю:<br /><br /><img src="https://cdn1.savepice.ru/uploads/2018/11/1/d49447175dd192a1dccb19358395f644-full.png" alt="результат в консоли" title="результат в консоли" class="UserPostedImage" style="max-width:200px;max-height:200px" /><br /><br /> <div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-csharp">public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
uint pcbStructInfo = 0;
byte[] raw = Convert.FromBase64String(File.ReadAllText("request.pem"));
CryptDecodeObject(65537,1,raw,raw.Length,0x8,IntPtr.Zero, ref pcbStructInfo);
Console.WriteLine("pcbStructInfo: " + pcbStructInfo);
IntPtr pvStructInfo = Marshal.AllocHGlobal((IntPtr)pcbStructInfo);
Console.WriteLine("pvStructInfo: " + pvStructInfo);
CryptDecodeObject(65537,1,raw,raw.Length,0x8,pvStructInfo, ref pcbStructInfo);
CERT_SIGNED_CONTENT_INFO str = new CERT_SIGNED_CONTENT_INFO();
str = Marshal.PtrToStructure<CERT_SIGNED_CONTENT_INFO>(pvStructInfo);
Console.WriteLine("str.SignatureAlgorithm.pszObjId: " + str.SignatureAlgorithm.pszObjId);
byte[] raw2 = getBytes(str);
uint pcbStructInfo2 = 0;
CryptDecodeObject(65537,4,raw2,raw2.Length,0x8,IntPtr.Zero, ref pcbStructInfo2);
Console.WriteLine("pcbStructInfo2: " + pcbStructInfo2);
/*
IntPtr pvStructInfo2 = Marshal.AllocHGlobal((IntPtr)pcbStructInfo2);
Console.WriteLine(pvStructInfo2);
CERT_REQUEST_INFO str2 = new CERT_REQUEST_INFO();
str = Marshal.PtrToStructure<CERT_SIGNED_CONTENT_INFO>(pvStructInfo2);
Console.WriteLine(str2.SubjectPublicKeyInfo.PublicKey.ToString());
*/
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
static byte[] getBytes(CERT_SIGNED_CONTENT_INFO str)
{
int size = Marshal.SizeOf(str);
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(str, ptr, false);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
[DllImport("crypt32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern Boolean CryptDecodeObject(
UInt32 dwCertEncodingType,
UInt32 lpszStructType,
byte[] pbEncoded,
Int32 cbEncoded,
UInt32 dwFlags,
IntPtr pvStructInfo,
ref UInt32 pcbStructInfo
);
public struct CERT_SIGNED_CONTENT_INFO {
public CRYPTOAPI_BLOB ToBeSigned;
public CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
public CRYPT_BIT_BLOB Signature;
}
public struct CRYPTOAPI_BLOB {
public UInt32 cbData;
public IntPtr pbData;
}
public struct CRYPT_ALGORITHM_IDENTIFIER {
[MarshalAs(UnmanagedType.LPStr)]
public String pszObjId;
public CRYPTOAPI_BLOB Parameters;
}
public struct CRYPT_BIT_BLOB {
public UInt32 cbData;
public IntPtr pbData;
public UInt32 cUnusedBits;
}
public struct CERT_REQUEST_INFO {
public uint dwVersion;
public CRYPTOAPI_BLOB Subject;
public CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo;
public uint cAttribute;
public CRYPT_ATTRIBUTE rgAttribute;
}
public struct CERT_PUBLIC_KEY_INFO {
public CRYPT_ALGORITHM_IDENTIFIER Algorithm;
public CRYPT_BIT_BLOB PublicKey;
}
public struct CRYPT_ATTRIBUTE {
public string pszObjId;
public UInt32 cValue;
public CRYPTOAPI_BLOB rgValue;
}</code></pre>
</div></div></td></tr></table>