将BouncyCastle签名转换为Crypto ++格式

时间:2018-02-23 12:18:17

标签: java c++ bouncycastle crypto++

ECDSA sign with BouncyCastle and verify with Crypto++给出的示例中,jenkins@jenkins-87c47bbb8-g87nw:/$ps -aux [...] jenkins [..] -jar /usr/share/jenkins/jenkins.war --argumentsRealm.passwd.jenkins=password --argumentsRealm.roles.jenkins=admin [...] 需要DSAConvertSignatureFormat()作为参数。但是从我的Java代码中得到的是,我得到了一个像byte[]

这样的签名
String

如何在Crypto ++代码中使用Java签名?

以下是问题中的Crypto ++代码:

302e021500f16529dcaddd3cec7616a3f94e157d1c28df8ea9021500997de4ae5497268c4f8eb3129abb11ca2abea9c1

以下是有问题的Java代码:

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;
}

1 个答案:

答案 0 :(得分: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个字节。

我认为该功能有其他问题,所以你可能想要朝另一个方向前进。

  

如何在Crypto ++代码中使用Java签名?

您可以使用类似于以下的代码。

您应该使用模式&str[0]来获取指向字符串第一个元素的非const指针。据我所知,它是获取非const指针的唯一明确定义的方法。其他一切都可能导致不确定的行为。

#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签名后调整大小。