Преобразование подписи BouncyCastle в формат Crypto ++

На примере, приведенном в ECDSA подписать с BouncyCastle и проверить с помощью Crypto ++, DSAConvertSignatureFormat() потребности byte[] в качестве аргументов. Но то, что я получил из своего кода Java, я получил такую ​​подпись, которая является String:

302e021500f16529dcaddd3cec7616a3f94e157d1c28df8ea9021500997de4ae5497268c4f8eb3129abb11ca2abea9c1

Как использовать подпись Java в коде Crypto ++?


Вот код Crypto ++ в вопросе:

bool VerifyMessage( const ECDSA<ECP, SHA256>::PublicKey& key, const string& message, const string& signature )
{
bool result = false;
string signatureFromJava("302e021500cb3333768bbe3f26d7a58388015d6110c1dbad5f021500dc2ee848c72deee1542939b3e5eb2816e71bf895");
SecByteBlock signatureFromJavaByte((byte *)signatureFromJava.data(), signatureFromJava.size());

byte finalSignature[0x40];
DSAConvertSignatureFormat(finalSignature, sizeof(finalSignature), DSA_P1363,
signatureFromJavaByte, sizeof(signatureFromJavaByte), DSA_DER);

// TODO convert finalSignature to std::string// Hexa encoding version, more readable
std::string decodedSignature;
StringSource(signature, true,
new HexDecoder(
new StringSink(decodedSignature)));

StringSource(decodedSignature+message, true,
new SignatureVerificationFilter(ECDSA<ECP,SHA256>::Verifier(key),
new ArraySink((byte*)&result,
sizeof(result))));

return result;
}

Вот этот Java-код:

public static String sign(String data) throws Exception {
KeyPair keyPair = loadKeyPair(System.getProperty("user.dir"),"ECDSA");
Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
signature.initSign(keyPair.getPrivate(), new SecureRandom());
byte[] message = data.getBytes();
signature.update(message);
byte[] sigBytes = signature.sign();
//verify("TEST", sigBytes);
String signatureStr = new BigInteger(1, sigBytes).toString(16);
return signatureStr;
}

1

Решение

Комментарий: сбой при вызове DSAConvertSignatureFormat ()

byte finalSignature[0x40];
DSAConvertSignatureFormat(finalSignature, sizeof(finalSignature), DSA_P1363,
signatureFromJavaByte, sizeof(signatureFromJavaByte), DSA_DER);

Авария потому что sizeof(signatureFromJavaByte) это размер std::stringа не длина строки. std::string 16 или около того байтов. Он состоит из 8 байтов для указателя и 8 байтов для хранения размера указанных данных. Вместо передачи 66-72 байтов в функцию, предоставляется только 16 или около того байтов.

Я думаю, что у функции есть другие проблемы, так что вы можете пойти в другом направлении.


Как использовать подпись Java в коде Crypto ++?

Вы можете использовать код, аналогичный приведенному ниже.

Вы должны использовать шаблон &str[0] чтобы получить неконстантный указатель на первый элемент строки. Насколько я знаю, это единственный четко определенный способ получить неконстантный указатель. Все остальное может привести к неопределенному поведению.

#define LOG_TAG "MY_PRODUCT"#define LOG_DEBUG(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#define LOG_INFO(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
#define LOG_WARN(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
#define LOG_ERROR(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))

bool VerifyMessage( const ECDSA<ECP, SHA256>::PublicKey& key, const string& message, const string& javaSignature )
{
ECDSA<ECP, SHA256>::Verifier verifier(key);
string ieeeSignature(0x40, '\0');

size_t size = DSAConvertSignatureFormat(
reinterpret_cast<byte*>(&ieeeSignature[0]), ieeeSignature.size(), DSA_P1363,
reinterpret_cast<const byte*>(&javaSignature[0]), javaSignature.size(), DSA_DER);
ASSERT(size == 0x40);

bool result = verifier.VerifyMessage(
reinterpret_cast<const byte*>(&message[0]), message.size(),
reinterpret_cast<const byte*>(&ieeeSignature[0]), ieeeSignature.size());

if (result)
LOG_INFO("VerifyMessage: verified message");
else
LOG_WARN("VerifyMessage: failed to verify message");

return result;
}

Назовите это следующим образом.

string javaSignature("302e021500cb3333768bbe3f26d7a58388015d6110c1dbad5f021500dc2ee848c72deee1542939b3e5eb2816e71bf895");
string derSignature;  // Hex decoded signature

StringSource(javaSignature, true, new HexDecoder(new StringSink(derSignature)));

bool verified = VerifyMessage(key, message, derSignature);

Вы также можете добавить функцию, подобную следующей, для преобразования произвольных подписей из DER в P1363:

std::string DER2P1363(const std::string& signature)
{
std::string result;
result.resize(256);

size_t size = DSAConvertSignatureFormat(
reinterpret_cast<byte*>(&result[0]), result.size(), DSA_P1363,
reinterpret_cast<const byte*>(&signature[0]), signature.size(), DSA_DER);

result.resize(size);
return result;
}

256 — это максимальная длина строки. Он будет изменен после преобразования подписи DER.

1

Другие решения

Других решений пока нет …