25.11.2004 21:08:15Как указать длину ключа при создании сертификата? Ответов: 11
Игорь
Сейчас я создаю сертификат и в строчке
"Открытый ключ" виндузного просмотрщика сертификата показывается OID алгоритма и "(0 Bits)", например
Открытый ключ 1.2.643.2.2.22(0 Bits)

Где нужно указать длину ключа, чтобы было не (0 Bits), а например (1024 Bits)?
Спасибо
 
Ответы:
26.11.2004 9:54:16Kirill Sobolev
Нужно установить КриптоПро CSP, т.к. длину ключа просмотрщик получает через функции провайдера.
26.11.2004 15:34:59Игорь
А как этот просмотрщик узнает:
1. к какому криптопровайдеру обратиться за информацией о ключе?
2. к какому алгоритму относится данный ключ сертификата? Ведь ключ в сертификате характеризуется OID’ом а в криптопровадере для идентификации алгоритма используется AlgID если не ошибаюсь...
26.11.2004 15:43:46Kirill Sobolev
По OID ключа конечно же. А как blob декодировать определяется с помощью чего-нибудь типа CryptGetOIDFunctionAddress
26.11.2004 19:28:12Игорь
Еще вопрос по составу сертификата. Как выводить кириллицу в полях сертификата?
29.11.2004 13:42:29Kirill Sobolev
Ну для начала установить шрифты, содержашие кириллицу... В остальном же вывод не отличается от вывода обычного текста.
29.03.2005 9:59:02Игорь
Сорри за торможениее...
Естественно, на машине есть русские шрифты, но тем не менее кириллица выводится козяброй в стандартном вьювере сертификата.
29.03.2005 10:42:37Kirill Sobolev
Какая ОС, какие языковые настройки?
Как создаете сертификат?
01.04.2005 12:03:51Игорь
ОС Win XP Professional SP1
кодовые страницы 855, 28595, 20880, 1251,10007

Сертификат создаю следующим образом:



#define ASN_E (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "advapi32.lib")

#define SIGN94_KEY 1
#define ENCRYPT_KEY 2
#define SIGN01_KEY 3

#define SIGN94_KEY_FNAME "my_sign_94.cer"
#define ENCRYPT_KEY_FNAME "my_encrypt.cer"
#define SIGN01_KEY_FNAME "my_sign_01.cer"

#define ALG_ID_SIGN01 "1.2.643.2.2.19"
#define ALG_ID_SIGN94 "1.2.643.2.2.20"
#define ALG_ID_ENCODE "1.2.643.2.2.22"


CERT_RDN_ATTR nameAttr;
PChar nameString;
CERT_RDN rdn;
CERT_NAME_INFO nameInfo;
CERT_REQUEST_INFO certReqInfo;
CERT_NAME_BLOB subjNameBlob;
DWORD encNameLen;
PBYTE encName;
HCRYPTPROV prov;
DWORD pubKeyInfoLen;
CERT_PUBLIC_KEY_INFO pubKeyInfo;
DWORD encCertReqLen;
CRYPT_OBJID_BLOB params;
CRYPT_ALGORITHM_IDENTIFIER sigAlg;
PBYTE signedEncCertReq;
PChar cont;
String err ;
DWORD encType;
CRYPT_BIT_BLOB PubKey;
CRYPT_ALGORITHM_IDENTIFIER PubKeyAlg;
HCRYPTPROV hCryptProv;
HCRYPTKEY phKey;
CERT_INFO certInfo,certInfo2,certInfo3;
LONGLONG serNum;
CERT_NAME_INFO nameInfoIss;
CERT_RDN_ATTR nameAttrIss;
CERT_RDN rdnIss;
CERT_NAME_BLOB issNameBlob;
DWORD encNameLenIss;
PBYTE encNameIss;

DWORD encCertLenIss;
PBYTE encCert;

// заполняю поля сруктуры запроса на серификат
nameAttr.pszObjId = "2.5.4.3";
nameAttr.dwValueType = CERT_RDN_PRINTABLE_STRING;
//здесь задаю имя владельца сертификата, которое потом выводится казябрами
nameAttr.Value.cbData = strlen(Form1->SubjectEdit->Text.c_str());
nameAttr.Value.pbData = Form1->SubjectEdit->Text.c_str();
rdn.cRDNAttr = 1;
rdn.rgRDNAttr = &nameAttr;
nameInfo.cRDN = 1;
nameInfo.rgRDN = &rdn;
// получаем размер закодированного имени пользователя
CryptEncodeObject (ASN_E, X509_NAME, &nameInfo, NULL, &encNameLen);
encName = (PBYTE) malloc(encNameLen);
//GetMem (encName, encNameLen);
CryptEncodeObject (ASN_E, X509_NAME, &nameInfo, encName, &encNameLen);
subjNameBlob.cbData = encNameLen;
subjNameBlob.pbData = encName;
certReqInfo.Subject = subjNameBlob;
certReqInfo.cAttribute = 0;
certReqInfo.rgAttribute = NULL;
certReqInfo.dwVersion = CERT_REQUEST_V1;
ZeroMemory(&params, sizeof(params));
sigAlg.pszObjId = szOID_OIWSEC_sha1RSASign;
sigAlg.Parameters = params;
// в структуре publickeyblobs находятся ключи, для которых я выпускаю сертификат
// в данном случае - подписи ’94
KeySign94Length=sizeof(publickeyblobs.Sign94Blob.publickey.pubkey94);
PubKeyAlg.pszObjId = ALG_ID_SIGN94; // подпись 94
PubKeyAlg.Parameters = params;
PubKey.cbData = KeySign94Length;
PubKey.pbData = publickeyblobs.Sign94Blob.publickey.pubkey94;
PubKey.cUnusedBits = 0;
pubKeyInfo.Algorithm = PubKeyAlg;
pubKeyInfo.PublicKey = PubKey;

certReqInfo.SubjectPublicKeyInfo = pubKeyInfo;
// подписываю структуру запроса
if(!CryptAcquireContext(&hCryptProv,"test",NULL,PROV_RSA_FULL,NULL))
CryptAcquireContext(&hCryptProv,"test",NULL,PROV_RSA_FULL,CRYPT_NEWKEYSET);
CryptGenKey(hCryptProv,CALG_RSA_SIGN,CRYPT_EXPORTABLE,&phKey);
CryptSignAndEncodeCertificate (hCryptProv, AT_SIGNATURE,ASN_E,X509_CERT_REQUEST_TO_BE_SIGNED, &certReqInfo, &sigAlg, NULL, NULL,&encCertReqLen);
signedEncCertReq = (PBYTE) malloc(encCertReqLen);
CryptSignAndEncodeCertificate (hCryptProv, AT_SIGNATURE,ASN_E, X509_CERT_REQUEST_TO_BE_SIGNED,&certReqInfo, &sigAlg, NULL, signedEncCertReq,&encCertReqLen);

// далее изготовляю сам сертификат
certInfo.dwVersion = 0;
//// серийный номер
if (!Form1->CheckBox1->Checked)
serNum = StrToInt64(Form1->serNumEdit->Text);
else
serNum = 1;
certInfo.SerialNumber.cbData = sizeof(serNum);
certInfo.SerialNumber.pbData = (BYTE *)&serNum;
certInfo.SignatureAlgorithm.pszObjId = szOID_OIWSEC_sha1RSASign;
certInfo.SignatureAlgorithm.Parameters = params;
nameAttrIss.pszObjId = "2.5.4.3";
nameAttrIss.dwValueType = CERT_RDN_PRINTABLE_STRING;
//здесь задаю имя того, кто выпускает сертификат, которое потом тоже выводится казябрами
nameAttrIss.Value.cbData = strlen(Form1->IssuerEdit->Text.c_str());
nameAttrIss.Value.pbData = Form1->IssuerEdit->Text.c_str();
rdnIss.cRDNAttr = 1;
rdnIss.rgRDNAttr = &nameAttrIss;
nameInfoIss.cRDN = 1;
nameInfoIss.rgRDN = &rdnIss;
CryptEncodeObject (ASN_E, X509_NAME, &nameInfoIss, NULL, &encNameLenIss);
encNameIss = (PBYTE) malloc(encNameLen);
CryptEncodeObject (ASN_E, X509_NAME, &nameInfoIss, encNameIss, &encNameLenIss);
issNameBlob.cbData = encNameLenIss;
issNameBlob.pbData = encNameIss;
certInfo.Issuer = issNameBlob;
// заполняю поля срока действия
SYSTEMTIME sysTime;
sysTime.wYear=0;
sysTime.wYear=0;
sysTime.wDay=0;
sysTime.wHour=0;
sysTime.wMinute=0;
sysTime.wSecond=0;
sysTime.wMilliseconds=0;
Form1->NotBeforeDTP1->DateTime.DecodeDate(&sysTime.wYear,&sysTime.wMonth,&sysTime.wDay);
sysTime.wDayOfWeek=Form1->NotBeforeDTP1->DateTime.DayOfWeek();
SystemTimeToFileTime (&sysTime,&(certInfo.NotBefore));
Form1->NotAfterDTP2->DateTime.DecodeDate(&sysTime.wYear,&sysTime.wMonth,&sysTime.wDay);
sysTime.wDayOfWeek=Form1->NotAfterDTP2->DateTime.DayOfWeek();
SystemTimeToFileTime (&sysTime, &(certInfo.NotAfter));

certInfo.Subject = certReqInfo.Subject;
certInfo.SubjectPublicKeyInfo = certReqInfo.SubjectPublicKeyInfo;
certInfo.IssuerUniqueId.cbData = 0;
certInfo.IssuerUniqueId.pbData = NULL;
certInfo.IssuerUniqueId.cUnusedBits = 0;
certInfo.SubjectUniqueId.cbData = 0;
certInfo.SubjectUniqueId.pbData = NULL;
certInfo.SubjectUniqueId.cUnusedBits = 0;
certInfo.cExtension = 0;
certInfo.rgExtension = NULL;
// генерирую сертификат
CryptSignAndEncodeCertificate (hCryptProv, AT_SIGNATURE, ASN_E,X509_CERT_TO_BE_SIGNED, &certInfo, &(certInfo.SignatureAlgorithm),NULL, NULL, &encCertLenIss);
encCert = (PBYTE) malloc(encCertLenIss);
CryptSignAndEncodeCertificate (hCryptProv, AT_SIGNATURE,ASN_E,X509_CERT_TO_BE_SIGNED, &certInfo, &(certInfo.SignatureAlgorithm), NULL, encCert, &encCertLenIss);

CryptReleaseContext (hCryptProv, 0);
01.04.2005 12:14:39Kirill Sobolev
CERT_RDN_PRINTABLE_STRING - это ANSI, конечно там русских символов нет.
надо использовать юникод
01.04.2005 19:22:04Игорь
Спасибо, помогло!
02.04.2005 6:26:11Игорь
Спасибо!