Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход. Новые регистрации запрещены.

Уведомление

Icon
Error

2 Страницы12>
Опции
К последнему сообщению К первому непрочитанному
Offline JCPplusCPP  
#1 Оставлено : 12 января 2009 г. 21:30:30(UTC)
JCPplusCPP

Статус: Новичок

Группы: Участники
Зарегистрирован: 12.01.2009(UTC)
Сообщений: 6
Откуда: Tver

Добрый вечер. Обращаюсь ко всем сведующим. Может подскажите, где ошибка в С-коде?

Проверил, что у меня везде один и тот же сертификат используется, один и тот же ключевой носитель.

Создаю ЭЦП C++:
Offline JCPplusCPP  
#2 Оставлено : 12 января 2009 г. 21:32:42(UTC)
JCPplusCPP

Статус: Новичок

Группы: Участники
Зарегистрирован: 12.01.2009(UTC)
Сообщений: 6
Откуда: Tver

Код:

int main(int argc, _TCHAR* argv[])
{
	CRYPT_DATA_BLOB SignedMessage;
    SignMessage(&SignedMessage);
     _tprintf(TEXT("Press any key to exit."));
    _getch();
}

bool SignMessage(CRYPT_DATA_BLOB *pSignedMessageBlob)
{
    bool fReturn = false;

    HCERTSTORE hCertStore = NULL;   
    PCCERT_CONTEXT pSignerCert; 
  
    DWORD cbSignedMessageBlob=0;
    BYTE  *pbSignedMessageBlob = NULL;
   BYTE  *pbSignature=NULL;
  DWORD dwSigLen=0;
   
LPBYTE pbUserCert;
HCRYPTKEY hKey = 0;
HCRYPTPROV phProv;
DWORD size;
DWORD fParam = CRYPT_FIRST;
PCCERT_CONTEXT pUserCert=0;
DWORD dwUserCertLength=0;
DWORD name_size;
char *SIGNER_NAME;
CString CERT_STORE;
CryptAcquireContext( &phProv,
				NULL,
				"Crypto-Pro GOST R 34.10-2001 Cryptographic ServiceProvider",                                                75,
				CRYPT_VERIFYCONTEXT
					);

while( CryptGetProvParam(phProv, PP_ENUMCONTAINERS, NULL, &size, fParam) )
{
BYTE * ContNameD=(BYTE*)malloc(sizeof(BYTE*)*size);
int len = (int)size;
CryptGetProvParam(phProv, PP_ENUMCONTAINERS, ContNameD, &size, fParam);
ContNameD[len]=0;
CERT_STORE = (CString) ContNameD;
_tprintf(CERT_STORE);
fParam = 0;
}

if(!CryptAcquireContext(&phProv,CERT_STORE,
              "Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider",75,CRYPT_MACHINE_KEYSET))
MyHandleError("CryptAcquireContext");


if(!CryptGetUserKey(phProv,AT_KEYEXCHANGE,&hKey))
MyHandleError("CryptGetUserKey");

if (!CryptGetKeyParam (hKey, KP_CERTIFICATE, NULL,&dwUserCertLength, 0)) 
{
MyHandleError ("Error during GetKeyParam.\n");
}

pbUserCert = (BYTE*)malloc (dwUserCertLength);
if (pbUserCert == NULL) 
{
MyHandleError ("Error during malloc.\n");
}
if (!CryptGetKeyParam (hKey, KP_CERTIFICATE, pbUserCert,&dwUserCertLength, 0)) 
{
MyHandleError ("Error during GetKeyParam.\n");
}

pUserCert = CertCreateCertificateContext (
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pbUserCert,
dwUserCertLength);
if (pUserCert == NULL) 
{
MyHandleError ("Error during CertCreateCertificateContext.\n");
}

name_size = CertNameToStr(MY_ENCODING_TYPE,
			  &(pUserCert->pCertInfo->Subject),
			  CERT_SIMPLE_NAME_STR,
			  NULL,
			  0);
if(!(SIGNER_NAME = (char *)malloc(name_size * sizeof(TCHAR))))
        {
            MyHandleError(TEXT("Memory allocation failed."));
        }
name_size = CertNameToStr(MY_ENCODING_TYPE,
			  &(pUserCert->pCertInfo->Subject),
			  CERT_SIMPLE_NAME_STR,
			  SIGNER_NAME,
			  name_size);
_tprintf(TEXT("Subject  -> %s.\n"), SIGNER_NAME);


  for(int l=0;l<=3;l++) *SIGNER_NAME=*SIGNER_NAME++;
_tprintf(TEXT("Subject  -> %s.\n"), SIGNER_NAME);

const int BuffSize = 1024;
WCHAR SIGNER_NAME1[BuffSize];

MultiByteToWideChar(CP_ACP, 0, SIGNER_NAME, strlen(SIGNER_NAME)+1, SIGNER_NAME1,strlen(SIGNER_NAME)+1);

	if(pbSignature)
        {
            free(pbSignature);
            pbSignature = NULL;
        }

   BYTE* pbMessage = (BYTE*)TEXT("12345");//SIGNER_NAME1;
   DWORD cbMessage = (DWORD)strlen((char*) pbMessage + 1) ;
   _tprintf(TEXT("The message to be signed is \n%s\n"),
        SIGNER_NAME1);
	_tprintf(TEXT("The message to be signed is \n%s\n"),
        pbMessage);
    if ( !( hCertStore = CertOpenStore(
       CERT_STORE_PROV_SYSTEM,
       0,
       NULL,
       CERT_SYSTEM_STORE_CURRENT_USER,
       CERT_STORE_NAME)))
    {
         MyHandleError(TEXT("The  store could not be opened."));
         goto exit_SignMessage;
    }

	if(pSignerCert = CertFindCertificateInStore(
       hCertStore,
       MY_ENCODING_TYPE,
       0,
       CERT_FIND_SUBJECT_STR,
       SIGNER_NAME1,
       NULL))
    {
      _tprintf(TEXT("The signer's certificate was found.\n"));
    }
    else
    {
        MyHandleError( TEXT("Signer certificate not found."));
        goto exit_SignMessage;
    }
  
HCRYPTHASH hHash;
if(CryptCreateHash(
    phProv, 
   	CALG_GR3411 , 
    0, 
    0, 
    &hHash)) 
  {
    printf("Hash object created.\n");
  }
  else
  {
		MyHandleError("error CryptCreateHash.");
  }

  if(CryptHashData(
    hHash, 
    pbMessage, 
    cbMessage, 
    0)) 
  {
    printf("Hash object vu4islen.\n");
  }
  else
  {
    MyHandleError("error  CryptHashData.");
  }
dwSigLen=0;pbSignature=NULL;
  if(CryptSignHash(
    hHash, 
    AT_KEYEXCHANGE,
    NULL, 
    0, 
    NULL, 
    &dwSigLen)) 
  {
    printf("Sign length %d .\n",dwSigLen);
  }
  else
  {
    MyHandleError("error CryptSignHash.");
  }

  if(pbSignature = new BYTE[dwSigLen]) 
  {
    printf("member for sign vudel.\n");
  }
  else
  {
    MyHandleError("member error.");
  }

  if(CryptSignHash(
    hHash, 
   AT_KEYEXCHANGE,
    NULL, 
    0, 
    pbSignature, 
    &dwSigLen)) 
  {
      print_signature(dwSigLen, pbSignature);
  }
  else
  {
    MyHandleError("error CryptSignHash.");
  }
  if(pbSignature)
    delete pbSignature;
  if(hHash) 
    CryptDestroyHash(hHash);
  if(phProv) 
    CryptReleaseContext(phProv, 0);
  if(pSignerCert)
    CertFreeCertificateContext(pSignerCert);
  if(CertCloseStore(hCertStore,  CERT_CLOSE_STORE_CHECK_FLAG))
  {
    printf("\nxran closed. \n");
  }
  else
  {
    printf("error!");
  }

exit_SignMessage:
	return TRUE;
}



Offline JCPplusCPP  
#3 Оставлено : 12 января 2009 г. 21:33:30(UTC)
JCPplusCPP

Статус: Новичок

Группы: Участники
Зарегистрирован: 12.01.2009(UTC)
Сообщений: 6
Откуда: Tver



Проверяю ЭЦП Java, вставляю в код значение хэша прямо из вывода С++ в хексовом виде:

Код:

import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Enumeration;

import org.apache.commons.codec.binary.Hex;

public class test {
	public static void main(String[] args) {
		int errcnt = 0;
			
			KeyStore keyStore = KeyStore.getInstance("OCFStore", "JCP");
				keyStore.load(null, "password".toCharArray());
				Enumeration en = keyStore.aliases();
				String alias = new String();

				while (en.hasMoreElements()) {
					alias = en.nextElement().toString();
					
					
						X509Certificate cert = (X509Certificate) keyStore
								.getCertificate(alias);
					
						PrivateKey privkey = (PrivateKey) keyStore.getKey(
								alias, "password".toCharArray());
						Signature sig = Signature.getInstance(
								"GOST3411withGOST3410EL", "JCP");
						sig.initSign(privkey);
						sig.update("12345".getBytes());
						byte[] signature = sig.sign();
						
//С такой переменной все проверяется удачно						String temp2 = new String(Hex.encodeHex(signature));
//эта переменная взята из вывода С++			
			String temp = "4e294a87d1db1026392db15119026a8384f6c19ea9e4270255c246d23521983dda92c3496bf380feffc3b6c93c8df1bcda08cea0576985d246d14ef770d70f3c";
						
						PublicKey pubkey = cert.getPublicKey();

						sig.initVerify(pubkey);
						sig.update("12345".getBytes());
						
						System.out.println( sig.verify(Hex.decodeHex(temp.toCharArray())) + " - signature test");
						
					
					
				}

			
		
		
	}
}
Offline ivan.novikov  
#4 Оставлено : 13 января 2009 г. 1:31:50(UTC)
ivan.novikov

Статус: Активный участник

Группы: Участники
Зарегистрирован: 23.05.2008(UTC)
Сообщений: 74
Откуда: Moscow

Насколько я JCP успел узнать, код на Java написан верно и отрабатывать должен корректно. temp2 - это, я так понимаю, как раз для проверки использовалось и работает правильно. Тогда остается две причины:

1. С++ код написан не корректно.
2. Не совместимы Jav'ский GOST3411withGOST3410EL и C'шный CALG_GR3411.

Во второе я решительно не верю
Offline ivan.novikov  
#5 Оставлено : 13 января 2009 г. 13:48:46(UTC)
ivan.novikov

Статус: Активный участник

Группы: Участники
Зарегистрирован: 23.05.2008(UTC)
Сообщений: 74
Откуда: Moscow

Так, кажется причина в том, что вы используете ключевую пару обмену, а попробуйте ключевую пару подписи....
Код:

if(CryptSignHash(
    hHash, 
  // AT_KEYEXCHANGE,
  AT_SIGNATURE,
    NULL, 
    0, 
    pbSignature, 
    &dwSigLen))


Господа опытные С++ криптографы, что скажите?
Offline Kirill Sobolev  
#6 Оставлено : 13 января 2009 г. 14:02:05(UTC)
Кирилл Соболев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 25.12.2007(UTC)
Сообщений: 1,733
Мужчина
Откуда: КРИПТО-ПРО

Поблагодарили: 177 раз в 168 постах
да, больше похоже на первое.
Цитата:
DWORD cbMessage = (DWORD)strlen((char*) pbMessage + 1) ;

вот в этом определении длины ошибка.
Вам надо убедиться, что CryptHashData получает теже данные, что и sig.update.
Техническую поддержку оказываем тут
Наша база знаний
Offline ivan.novikov  
#7 Оставлено : 13 января 2009 г. 15:01:24(UTC)
ivan.novikov

Статус: Активный участник

Группы: Участники
Зарегистрирован: 23.05.2008(UTC)
Сообщений: 74
Откуда: Moscow

Может я плохо понимаю С++, но где в коде сверху связка сертификата, закрытого ключа и самой функции вычисления подписи?
Я вижу, что там нашли второй сертификат
Код:

if(pSignerCert = CertFindCertificateInStore(
       hCertStore,
       MY_ENCODING_TYPE,
       0,
       CERT_FIND_SUBJECT_STR,
       SIGNER_NAME1,
       NULL))
    {
      _tprintf(TEXT("The signer's certificate was found.\n"));
    }
    else
    {
        MyHandleError( TEXT("Signer certificate not found."));
        goto exit_SignMessage;
    }

И ВСЕ! Этот объект больше нигде не используется. Или это просто незакомментированный кусок кода. Тогда все ясно.

Отредактировано пользователем 13 января 2009 г. 15:15:34(UTC)  | Причина: Не указана

Offline JCPplusCPP  
#8 Оставлено : 13 января 2009 г. 15:10:48(UTC)
JCPplusCPP

Статус: Новичок

Группы: Участники
Зарегистрирован: 12.01.2009(UTC)
Сообщений: 6
Откуда: Tver

Kirill Sobolev написал:
да, больше похоже на первое.
Цитата:
DWORD cbMessage = (DWORD)strlen((char*) pbMessage + 1) ;

вот в этом определении длины ошибка.
Вам надо убедиться, что CryptHashData получает теже данные, что и sig.update.


Спасибо большое за комментарий!

Для проверки написал вот так "в лоб":
Код:

BYTE* pbMessage = (BYTE*)TEXT("12345");//SIGNER_NAME1;
DWORD cbMessage = (DWORD)5;

Результат тот же самый! Всегда false...

Может в хекс не парвильно перевожу?
Код:

void print_signature(DWORD cbSigned, BYTE* pbSigned)
{
    for(DWORD i=0; i < cbSigned; i++) 
    {
      printf("%2.2x", pbSigned[i]);
      if ((i+1)%32 == 0) printf("\n");
    }
	printf("length is:%d",cbSigned);
}

Offline ivan.novikov  
#9 Оставлено : 13 января 2009 г. 16:03:23(UTC)
ivan.novikov

Статус: Активный участник

Группы: Участники
Зарегистрирован: 23.05.2008(UTC)
Сообщений: 74
Откуда: Moscow

В хекс все правильно переводится, проверим функцию. Опыт с Вашими исходниками полностью повторил.
Результат тот же самый.
Неужели разные ГОСТ алгоритмы 3411 в JCP и CSP?

Неплохое запад...

В примерах из SDK нашел еще вызовы CryptGetHashParam до самого хэширования, может в них дело.

Отредактировано пользователем 13 января 2009 г. 16:08:21(UTC)  | Причина: Не указана

Offline Serge3leo  
#10 Оставлено : 13 января 2009 г. 16:54:12(UTC)
Serge3leo

Статус: Активный участник

Группы: Участники
Зарегистрирован: 28.01.2008(UTC)
Сообщений: 40
Мужчина
Откуда: Москва

Поблагодарили: 3 раз в 2 постах
Мне показалось, или это действительно так.

В подписывали данные типа wchar_t (UCS-2 в виде Little-Endian), которые возвратил макрос TEXT(), а он на Java имеет иное представление.

Рекомендую подписывать текст в UTF-8. А если используются "широкие" символы, то тщательно согласовывать их ширину (UCS-2/UCS-4) и их ориентацию "остроконечный"/"тупоконечный"

P.S.

Быть может попробовать:

BYTE pbMessage[] = "12345";
DWORD cbMessage = (DWORD)5;

А то вы подписывали, по моему разумению, 2.5 символа, что не есть хорошо.

Отредактировано пользователем 13 января 2009 г. 17:06:11(UTC)  | Причина: Не указана

RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
2 Страницы12>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.