tests: In benchmarks, added crypto for C encoding and decoding.
diff --git a/tests/test-encode-decode-benchmark.cpp b/tests/test-encode-decode-benchmark.cpp
index 98234ca..2f0979b 100644
--- a/tests/test-encode-decode-benchmark.cpp
+++ b/tests/test-encode-decode-benchmark.cpp
@@ -21,6 +21,7 @@
#include "../src/c/encoding/binary-xml-decoder.h"
#include "../src/c/data.h"
#include "../src/c/encoding/binary-xml-data.h"
+#include "../src/c/util/crypto.h"
using namespace std;
using namespace ndn;
@@ -34,6 +35,33 @@
return t.tv_sec + t.tv_usec / 1000000.0;
}
+static bool
+verifyRsaSignature
+ (uint8_t* signedPortion, size_t signedPortionLength, uint8_t* signatureBits, size_t signatureBitsLength,
+ uint8_t* publicKeyDer, size_t publicKeyDerLength)
+{
+ // Set signedPortionDigest to the digest of the signed portion of the wire encoding.
+ uint8_t signedPortionDigest[SHA256_DIGEST_LENGTH];
+ ndn_digestSha256(signedPortion, signedPortionLength, signedPortionDigest);
+
+ // Verify the signedPortionDigest.
+ // Use a temporary pointer since d2i updates it.
+ const uint8_t *derPointer = publicKeyDer;
+ RSA *rsaPublicKey = d2i_RSA_PUBKEY(NULL, &derPointer, publicKeyDerLength);
+ if (!rsaPublicKey) {
+ // Don't expect this to happen.
+ cout << "Error decoding public key in d2i_RSAPublicKey" << endl;
+ return 0;
+ }
+ int success = RSA_verify
+ (NID_sha256, signedPortionDigest, sizeof(signedPortionDigest), signatureBits, signatureBitsLength, rsaPublicKey);
+ // Free the public key before checking for success.
+ RSA_free(rsaPublicKey);
+
+ // RSA_verify returns 1 for a valid signature.
+ return (success == 1);
+}
+
static uint8_t DEFAULT_PUBLIC_KEY_DER[] = {
0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81,
0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xE1, 0x7D, 0x30, 0xA7, 0xD8, 0x28, 0xAB, 0x1B, 0x84, 0x0B, 0x17,
@@ -150,6 +178,7 @@
KeyLocator keyLocator;
keyLocator.setType(ndn_KeyLocatorType_KEYNAME);
keyLocator.setKeyName(certificateName);
+ keyLocator.setKeyNameType((ndn_KeyNameType)-1);
Sha256WithRsaSignature* sha256Signature = (Sha256WithRsaSignature*)data.getSignature();
sha256Signature->setKeyLocator(keyLocator);
sha256Signature->getPublisherPublicKeyDigest().setPublisherPublicKeyDigest(publisherPublicKeyDigest);
@@ -265,14 +294,24 @@
ndn_Name_appendString(&certificateName, (char*)"0");
// Set up publisherPublicKeyDigest and signatureBits in case useCrypto is false.
- uint8_t publisherPublicKeyDigestArray[32];
- memset(publisherPublicKeyDigestArray, 0, sizeof(publisherPublicKeyDigestArray));
+ uint8_t* publicKeyDer = DEFAULT_PUBLIC_KEY_DER;
+ size_t publicKeyDerLength = sizeof(DEFAULT_PUBLIC_KEY_DER);
+ uint8_t publisherPublicKeyDigestArray[SHA256_DIGEST_LENGTH];
+ ndn_digestSha256(publicKeyDer, publicKeyDerLength, publisherPublicKeyDigestArray);
struct ndn_Blob publisherPublicKeyDigest;
ndn_Blob_initialize(&publisherPublicKeyDigest, publisherPublicKeyDigestArray, sizeof(publisherPublicKeyDigestArray));
uint8_t signatureBitsArray[128];
memset(signatureBitsArray, 0, sizeof(signatureBitsArray));
- struct ndn_Blob signatureBits;
- ndn_Blob_initialize(&signatureBits, signatureBitsArray, sizeof(signatureBitsArray));
+
+ // Set up the private key now in case useCrypto is true.
+ // Use a temporary pointer since d2i updates it.
+ const uint8_t *privateKeyDerPointer = DEFAULT_PRIVATE_KEY_DER;
+ RSA *privateKey = d2i_RSAPrivateKey(NULL, &privateKeyDerPointer, sizeof(DEFAULT_PRIVATE_KEY_DER));
+ if (!privateKey) {
+ // Don't expect this to happen.
+ cout << "Error decoding private key DER" << endl;
+ return 0;
+ }
double start = getNowSeconds();
for (int i = 0; i < nIterations; ++i) {
@@ -287,34 +326,54 @@
ndn_NameComponent_initialize(&data.metaInfo.finalBlockID, finalBlockId.value, finalBlockId.length);
}
- if (useCrypto)
- // This sets the signature fields.
- throw runtime_error("C signing not implemented");
- else {
- // Imitate IdentityManager::signByCertificate to set up the signature fields, but don't sign.
- data.signature.keyLocator.type = ndn_KeyLocatorType_KEYNAME;
- data.signature.keyLocator.keyName = certificateName;
- data.signature.publisherPublicKeyDigest.publisherPublicKeyDigest = publisherPublicKeyDigest;
- data.signature.signature = signatureBits;
- }
-
struct ndn_DynamicUInt8Array output;
- // Assume the encoding buffer is big enough so we don't need to dynamically reallocate.
- ndn_DynamicUInt8Array_initialize(&output, encoding, maxEncodingLength, 0);
struct ndn_BinaryXmlEncoder encoder;
- ndn_BinaryXmlEncoder_initialize(&encoder, &output);
-
size_t signedPortionBeginOffset, signedPortionEndOffset;
ndn_Error error;
+
+ data.signature.keyLocator.type = ndn_KeyLocatorType_KEYNAME;
+ data.signature.keyLocator.keyName = certificateName;
+ data.signature.keyLocator.keyNameType = (ndn_KeyNameType)-1;
+ data.signature.publisherPublicKeyDigest.publisherPublicKeyDigest = publisherPublicKeyDigest;
+ if (useCrypto) {
+ // Encode once to get the signed portion.
+ ndn_DynamicUInt8Array_initialize(&output, encoding, maxEncodingLength, 0);
+ ndn_BinaryXmlEncoder_initialize(&encoder, &output);
+ if ((error = ndn_encodeBinaryXmlData(&data, &signedPortionBeginOffset, &signedPortionEndOffset, &encoder))) {
+ cout << "Error in ndn_encodeBinaryXmlData: " << ndn_getErrorString(error) << endl;
+ return 0;
+ }
+
+ // Imitate MemoryPrivateKeyStorage::sign.
+ uint8_t digest[SHA256_DIGEST_LENGTH];
+ ndn_digestSha256(encoding + signedPortionBeginOffset, signedPortionEndOffset - signedPortionBeginOffset, digest);
+ unsigned int signatureBitsLength;
+ if (!RSA_sign(NID_sha256, digest, sizeof(digest), signatureBitsArray, &signatureBitsLength, privateKey)) {
+ // Don't expect this to happen.
+ cout << "Error in RSA_sign" << endl;
+ return 0;
+ }
+
+ ndn_Blob_initialize(&data.signature.signature, signatureBitsArray, signatureBitsLength);
+ }
+ else
+ // Set up the signature, but don't sign.
+ ndn_Blob_initialize(&data.signature.signature, signatureBitsArray, sizeof(signatureBitsArray));
+
+ // Assume the encoding buffer is big enough so we don't need to dynamically reallocate.
+ ndn_DynamicUInt8Array_initialize(&output, encoding, maxEncodingLength, 0);
+ ndn_BinaryXmlEncoder_initialize(&encoder, &output);
if ((error = ndn_encodeBinaryXmlData(&data, &signedPortionBeginOffset, &signedPortionEndOffset, &encoder))) {
cout << "Error in ndn_encodeBinaryXmlData: " << ndn_getErrorString(error) << endl;
return 0;
- }
-
+ }
*encodingLength = encoder.offset;
}
double finish = getNowSeconds();
+ if (privateKey)
+ RSA_free(privateKey);
+
return finish - start;
}
@@ -333,19 +392,27 @@
for (int i = 0; i < nIterations; ++i) {
struct ndn_NameComponent nameComponents[100];
struct ndn_NameComponent keyNameComponents[100];
- struct ndn_Data dataStruct;
+ struct ndn_Data data;
ndn_Data_initialize
- (&dataStruct, nameComponents, sizeof(nameComponents) / sizeof(nameComponents[0]),
+ (&data, nameComponents, sizeof(nameComponents) / sizeof(nameComponents[0]),
keyNameComponents, sizeof(keyNameComponents) / sizeof(keyNameComponents[0]));
ndn_BinaryXmlDecoder decoder;
ndn_BinaryXmlDecoder_initialize(&decoder, encoding, encodingLength);
size_t signedPortionBeginOffset, signedPortionEndOffset;
ndn_Error error;
- if ((error = ndn_decodeBinaryXmlData(&dataStruct, &signedPortionBeginOffset, &signedPortionEndOffset, &decoder))) {
+ if ((error = ndn_decodeBinaryXmlData(&data, &signedPortionBeginOffset, &signedPortionEndOffset, &decoder))) {
cout << "Error in ndn_decodeBinaryXmlData: " << ndn_getErrorString(error) << endl;
return 0;
}
+
+ if (useCrypto) {
+ if (!verifyRsaSignature
+ (encoding + signedPortionBeginOffset, signedPortionEndOffset - signedPortionBeginOffset,
+ data.signature.signature.value, data.signature.signature.length,
+ DEFAULT_PUBLIC_KEY_DER, sizeof(DEFAULT_PUBLIC_KEY_DER)))
+ cout << "Signature verification: FAILED" << endl;
+ }
}
double finish = getNowSeconds();
@@ -369,7 +436,7 @@
<< ", Duration sec, Hz: " << duration << ", " << (nIterations / duration) << endl;
}
{
- int nIterations = useCrypto ? 100000 : 500000;;
+ int nIterations = useCrypto ? 100000 : 500000;
double duration = benchmarkDecodeDataSecondsCpp(nIterations, useCrypto, encoding);
cout << "Decode " << (useComplex ? "complex" : "simple ") << " data C++: Crypto? " << (useCrypto ? "yes" : "no ")
<< ", Duration sec, Hz: " << duration << ", " << (nIterations / duration) << endl;
@@ -394,7 +461,7 @@
<< ", Duration sec, Hz: " << duration << ", " << (nIterations / duration) << endl;
}
{
- int nIterations = useCrypto ? 100000 : 15000000;
+ int nIterations = useCrypto ? 150000 : 15000000;
double duration = benchmarkDecodeDataSecondsC(nIterations, useCrypto, encoding, encodingLength);
cout << "Decode " << (useComplex ? "complex" : "simple ") << " data C: Crypto? " << (useCrypto ? "yes" : "no ")
<< ", Duration sec, Hz: " << duration << ", " << (nIterations / duration) << endl;
@@ -412,6 +479,8 @@
benchmarkEncodeDecodeDataC(false, false);
benchmarkEncodeDecodeDataC(true, false);
+ benchmarkEncodeDecodeDataC(false, true);
+ benchmarkEncodeDecodeDataC(true, true);
} catch (std::exception& e) {
cout << "exception: " << e.what() << endl;
}