05.03.2007 14:08:53Совместимось CSP и JCP. Ответов: 7
Андрей
Подпись сделанная в CSP не проверяется в JCP и наоборот. Эти два продукта совместимы между собой?
 
Ответы:
05.03.2007 18:50:05Андрей
Нашел вопрос, который задавали в этом форуме - http://cryptopro.ru/cryptopro/forum/view.asp?q=2355

У меня абсолютно такая же ситуация. Только на тот вопрос так и не ответили.
Может разработчики CSP все-таки ответят на вопрос, что именно подписывает функция CryptSignMessage? На сколько я понимаю, JCP генерирует такую же подпись как и функция CryptSignMessage, только вот по ГОСТу ли это?
07.03.2007 16:58:55bor1
Все по ГОСТ работает. Попробуйте объект подписи запрашивать так:
Signature sig = Signature.getInstance("CryptoProSignature");
12.03.2007 16:17:08Андрей
Все равно не проверяется.

Вот код который генерирует подпись при помощи CAPILite под Солярисом:

if( CryptAcquireContext(&hProv, (const char *)pContainer, NULL, typeProv, 0) ) {
/*
* Создаем хеш.
*/
if ( CryptCreateHash(hProv, CALG_GR3411, 0, 0, &hHash) ) {
/*
* Устанавливаем HP_OID.
* Заносим данные в созданный хеш и подписываем их.
*/
if ( CryptSetHashParam(hHash,HP_OID,(BYTE*)OID_HashVerbaO, 0) &&
CryptSetHashParam(hHash, HP_HASHVAL, (const BYTE *)pHash, 0) ) {
if( CryptSignHash( hHash, AT_SIGNATURE, NULL, 0, NULL, &cbSignature) ) {
isKey = TRUE;
setKey = AT_SIGNATURE;
} else if( CryptSignHash( hHash, AT_KEYEXCHANGE, NULL, 0, NULL, &cbSignature) ) {
printf("sign: SIGNATURE key not found. Using KEYEXCHANGE key.\n");
isKey = TRUE;
setKey = AT_KEYEXCHANGE;
}

if( isKey && (pbSignature = new BYTE[cbSignature]) ) {
if( CryptSignHash(hHash, setKey, NULL, 0, pbSignature, &cbSignature) ) {
/*
* Возвращаем подписанные данные.
*/
....
} else {
PrintError("4. Error CryptSignHash");
}
delete[] pbSignature;
} else {
PrintError("4. Error CryptSignHash or size");
}
} else {
PrintError("4. Error CryptSetHashParam or size");
}
CryptDestroyHash(hHash);
} else {
PrintError("4. Error CryptCreateHash");
}
CryptReleaseContext(hProv, 0);
} else {
PrintError("4. Error CryptAcquireContext");
}



Код проверки на Java при помощи JCP под Линуксом:

public abstract class AbstractTest {

// данные, которые будут подписываться
public static final String DATA_FOR_SIGN = "Data for sign.";

// Digest: И CSP и JCP генерируют одинаковый дайджест
// -17 39 -37 66 -51 -43 -76 37 8 -113 -122 52 40 -58 -75 -18 55 -62 -60 82 61 41 -88 82 -126 106 -48 -94 63 18 43 110


// цифровая подпись вычисленная с данных - AbstractTest#DATA_FOR_SIGN.
public static final byte[] SIGNATURE =

{ -10, -46, -40, 68, -43, 67, -58, -54, -92, 27, -85, -45, 89, 107, -52,
-35, -66, -127, 3, -104, -78, -59, -90, 102, -14, -12, -100, -122, -48,
-47, -12, 46, -59, 34, -31, 68, -6, -67, -84, -110, 64, -101, -23, 72,
35, 51, -23, -22, 116, -76, -20, -29, -26, -13, -15, 104, 77, 109, -96,
-107, -15, -86, -25, -70, }; // Подпись сгенерированная CSP. Самим CSP проверяется, как под Линуксом, так и под Солярисом.

// название алгоритма хеширования
public static final String MESSAGE_DIGEST_ALGORITHM = «GOST3411»;

// название алгоритма ЭЦП.
public static final String SIGNATURE_ALGORITHM = «GOST3411withGOST3410EL»;
// public static final String SIGNATURE_ALGORITHM = «CryptoProSignature»; // так тоже не проверяется

...

}


public class VerifyTest extends AbstractTest {

public VerifyTest() {
}


public static void main( String[] args ) {
try {
System.out.println( "Validation begin..." );
System.out.println( "Store type - " + STORE_TYPE );
System.out.println( "Container name - " + USER_ALIAS );

// загружаем хранилище сертификатов и закрытых ключей
KeyStore store = KeyStore.getInstance( STORE_TYPE );
store.load( null, null );

// получаем сертификат из хранилища
X509Certificate cert =
( X509Certificate )store.getCertificate( USER_ALIAS );

// Получаем открытый ключ из сертификата
PublicKey pubKey = cert.getPublicKey();

// вычисляем дайджест из данных, чья ЭЦП будет проверяться
MessageDigest digest =
MessageDigest.getInstance( MESSAGE_DIGEST_ALGORITHM );
digest.update( DATA_FOR_SIGN.getBytes() );
byte[] digestedData = digest.digest();
outByteArray( digestedData, "Digest:" );

// проверяем подпись
Signature sig = Signature.getInstance( SIGNATURE_ALGORITHM );

sig.initVerify( pubKey );
sig.update( digestedData );
boolean success = sig.verify( SIGNATURE );

if ( success ) {
System.out.println( "Validation SUCCESSFUL." );
} else {
System.out.println( "Validation FAILED." );
}

//verify();

} catch ( Exception e ) {
e.printStackTrace();
}
}

}

Код возвращает - Validation FAILED.

В чем может быть проблема ?

CSP используется версии 3.0.
12.03.2007 16:24:42Андрей
Ради эксперимента сделал следующее:

Сделал подпись в JCP со следующим параметром – Signature.getInstance("CryptoProSignature"), проверил с таким же параметром, подпись проверяется. Затем сгенерированную ранее подпись проверил с параметром Signature.getInstance("GOST3411withGOST3410EL"), JCP сказал, что подпись не валидна. Объясните пожалуйста, если указан параметр «CryptoProSignature», по какому алгоритму генерируется/проверяется подпись? В документации к JCP описание параметра CryptoProSignature я не нашел. Какое-то раздвоение ГОСТ-ов получается.
12.03.2007 17:04:45bor1
Разница между этими алгоритмами в порядке байтов в массиве подписи :) Других отличий нет.
"Алгоритм" "CryptoProSignature" был введен специально для совместимости с подписью CSP.

Сейчас я попробую запустить ваш пример.
12.03.2007 18:25:15Андрей
Странная ситуация возникла. При формировании подписи в CSP я сначала высчитывал дайджест с подписываемых данных (CryptCreateHash()) и подписывал потом именно его (CryptSignHash()). При проверке этой подписи на Java я высчитывал дайджест с тех же самых данных (Digest#digest()) и полученное значение передавал в метод Signature#update(). В метод Signature#verify() передавал подпись сгенерированную CSP. Подпись не проверялась.

Но если в Java при проверке подписи сделанной в CSP в метод Signature#update() передавать не заранее вычисленный дайджест, а данные в исходном виде, то подпись проверяется! Т.е. получается, что JCP автоматически и в любом случае вычисляет дайджест с проверяемых данных??? Так ли это? В документации я не нашел информации о том, что при вызове метода Signature#verify() JCP автоматически вычислит дайджест с данных переданных через метод Signature#update().
12.03.2007 18:32:39bor1
Ну да, все правильно. Вы действительно просто подписывали хеш на хеш. В объект подписи в Java передаются данные, а не значение хеша.