Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Unified Diff: content/child/webcrypto/test/rsa_pss_unittest.cc

Issue 661653002: [webcrypto] Implement RSA-PSS using BoringSSL. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@refactor_rsassa
Patch Set: rebase onto master (corrected) Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/child/webcrypto/platform_crypto.h ('k') | content/child/webcrypto/test/test_helpers.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/child/webcrypto/test/rsa_pss_unittest.cc
diff --git a/content/child/webcrypto/test/rsa_pss_unittest.cc b/content/child/webcrypto/test/rsa_pss_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..097f6bcae6ab16903277abf1a4547b3b68d7f5de
--- /dev/null
+++ b/content/child/webcrypto/test/rsa_pss_unittest.cc
@@ -0,0 +1,302 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "content/child/webcrypto/algorithm_dispatch.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/jwk.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/test/test_helpers.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+#include "third_party/WebKit/public/platform/WebCryptoKey.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+bool SupportsRsaPss() {
+#if defined(USE_OPENSSL)
+ return true;
+#else
+ return false;
+#endif
+}
+
+blink::WebCryptoAlgorithm CreateRsaPssAlgorithm(
+ unsigned int salt_length_bytes) {
+ return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
+ blink::WebCryptoAlgorithmIdRsaPss,
+ new blink::WebCryptoRsaPssParams(salt_length_bytes));
+}
+
+// Test that no two RSA-PSS signatures are identical, when using a non-zero
+// lengthed salt.
+TEST(WebCryptoRsaPssTest, SignIsRandom) {
+ if (!SupportsRsaPss()) {
+ LOG(WARNING) << "Skipping test because RSA-PSS is not supported";
+ return;
+ }
+
+ // Import public/private key pair.
+ blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
+ blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
+
+ ImportRsaKeyPair(
+ HexStringToBytes(kPublicKeySpkiDerHex),
+ HexStringToBytes(kPrivateKeyPkcs8DerHex),
+ CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaPss,
+ blink::WebCryptoAlgorithmIdSha1),
+ true,
+ blink::WebCryptoKeyUsageVerify,
+ blink::WebCryptoKeyUsageSign,
+ &public_key,
+ &private_key);
+
+ // Use a 20-byte length salt.
+ blink::WebCryptoAlgorithm params = CreateRsaPssAlgorithm(20);
+
+ // Some random message to sign.
+ std::vector<uint8_t> message = HexStringToBytes(kPublicKeySpkiDerHex);
+
+ // Sign twice.
+ std::vector<uint8_t> signature1;
+ std::vector<uint8_t> signature2;
+
+ ASSERT_EQ(Status::Success(),
+ Sign(params, private_key, CryptoData(message), &signature1));
+ ASSERT_EQ(Status::Success(),
+ Sign(params, private_key, CryptoData(message), &signature2));
+
+ // The signatures will be different because of the salt.
+ EXPECT_NE(CryptoData(signature1), CryptoData(signature2));
+
+ // However both signatures should work when verifying.
+ bool is_match = false;
+
+ ASSERT_EQ(Status::Success(),
+ Verify(params,
+ public_key,
+ CryptoData(signature1),
+ CryptoData(message),
+ &is_match));
+ EXPECT_TRUE(is_match);
+
+ ASSERT_EQ(Status::Success(),
+ Verify(params,
+ public_key,
+ CryptoData(signature2),
+ CryptoData(message),
+ &is_match));
+ EXPECT_TRUE(is_match);
+
+ // Corrupt the signature and verification must fail.
+ ASSERT_EQ(Status::Success(),
+ Verify(params,
+ public_key,
+ CryptoData(Corrupted(signature2)),
+ CryptoData(message),
+ &is_match));
+ EXPECT_FALSE(is_match);
+}
+
+// Try signing and verifying when the salt length is 0. The signature in this
+// case is not random.
+TEST(WebCryptoRsaPssTest, SignVerifyNoSalt) {
+ if (!SupportsRsaPss()) {
+ LOG(WARNING) << "Skipping test because RSA-PSS is not supported";
+ return;
+ }
+
+ // Import public/private key pair.
+ blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
+ blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
+
+ ImportRsaKeyPair(
+ HexStringToBytes(kPublicKeySpkiDerHex),
+ HexStringToBytes(kPrivateKeyPkcs8DerHex),
+ CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaPss,
+ blink::WebCryptoAlgorithmIdSha1),
+ true,
+ blink::WebCryptoKeyUsageVerify,
+ blink::WebCryptoKeyUsageSign,
+ &public_key,
+ &private_key);
+
+ // Zero-length salt.
+ blink::WebCryptoAlgorithm params = CreateRsaPssAlgorithm(0);
+
+ // Some random message to sign.
+ std::vector<uint8_t> message = HexStringToBytes(kPublicKeySpkiDerHex);
+
+ // Sign twice.
+ std::vector<uint8_t> signature1;
+ std::vector<uint8_t> signature2;
+
+ ASSERT_EQ(Status::Success(),
+ Sign(params, private_key, CryptoData(message), &signature1));
+ ASSERT_EQ(Status::Success(),
+ Sign(params, private_key, CryptoData(message), &signature2));
+
+ // The signatures will be the same this time.
+ EXPECT_EQ(CryptoData(signature1), CryptoData(signature2));
+
+ // Make sure that verification works.
+ bool is_match = false;
+ ASSERT_EQ(Status::Success(),
+ Verify(params,
+ public_key,
+ CryptoData(signature1),
+ CryptoData(message),
+ &is_match));
+ EXPECT_TRUE(is_match);
+
+ // Corrupt the signature and verification must fail.
+ ASSERT_EQ(Status::Success(),
+ Verify(params,
+ public_key,
+ CryptoData(Corrupted(signature2)),
+ CryptoData(message),
+ &is_match));
+ EXPECT_FALSE(is_match);
+}
+
+TEST(WebCryptoRsaPssTest, SignEmptyMessage) {
+ if (!SupportsRsaPss()) {
+ LOG(WARNING) << "Skipping test because RSA-PSS is not supported";
+ return;
+ }
+
+ // Import public/private key pair.
+ blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
+ blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
+
+ ImportRsaKeyPair(
+ HexStringToBytes(kPublicKeySpkiDerHex),
+ HexStringToBytes(kPrivateKeyPkcs8DerHex),
+ CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaPss,
+ blink::WebCryptoAlgorithmIdSha1),
+ true,
+ blink::WebCryptoKeyUsageVerify,
+ blink::WebCryptoKeyUsageSign,
+ &public_key,
+ &private_key);
+
+ blink::WebCryptoAlgorithm params = CreateRsaPssAlgorithm(20);
+ std::vector<uint8_t> message; // Empty message.
+ std::vector<uint8_t> signature;
+
+ ASSERT_EQ(Status::Success(),
+ Sign(params, private_key, CryptoData(message), &signature));
+
+ // Make sure that verification works.
+ bool is_match = false;
+ ASSERT_EQ(Status::Success(),
+ Verify(params,
+ public_key,
+ CryptoData(signature),
+ CryptoData(message),
+ &is_match));
+ EXPECT_TRUE(is_match);
+
+ // Corrupt the signature and verification must fail.
+ ASSERT_EQ(Status::Success(),
+ Verify(params,
+ public_key,
+ CryptoData(Corrupted(signature)),
+ CryptoData(message),
+ &is_match));
+ EXPECT_FALSE(is_match);
+}
+
+// Iterate through known answers and test verification.
+// * Verify over original message should succeed
+// * Verify over corrupted message should fail
+// * Verification with corrupted signature should fail
+TEST(WebCryptoRsaPssTest, VerifyKnownAnswer) {
+ if (!SupportsRsaPss()) {
+ LOG(WARNING) << "Skipping test because RSA-PSS is not supported";
+ return;
+ }
+
+ scoped_ptr<base::DictionaryValue> test_data;
+ ASSERT_TRUE(ReadJsonTestFileToDictionary("rsa_pss.json", &test_data));
+
+ const base::DictionaryValue* keys_dict = NULL;
+ ASSERT_TRUE(test_data->GetDictionary("keys", &keys_dict));
+
+ const base::ListValue* tests = NULL;
+ ASSERT_TRUE(test_data->GetList("tests", &tests));
+
+ for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
+ SCOPED_TRACE(test_index);
+
+ const base::DictionaryValue* test;
+ ASSERT_TRUE(tests->GetDictionary(test_index, &test));
+
+ blink::WebCryptoAlgorithm hash = GetDigestAlgorithm(test, "hash");
+
+ std::string key_name;
+ ASSERT_TRUE(test->GetString("key", &key_name));
+
+ // Import the public key.
+ blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
+ std::vector<uint8_t> spki_bytes =
+ GetBytesFromHexString(keys_dict, key_name);
+
+ ASSERT_EQ(Status::Success(),
+ ImportKey(blink::WebCryptoKeyFormatSpki,
+ CryptoData(spki_bytes),
+ CreateRsaHashedImportAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaPss, hash.id()),
+ true,
+ blink::WebCryptoKeyUsageVerify,
+ &public_key));
+
+ int saltLength;
+ ASSERT_TRUE(test->GetInteger("saltLength", &saltLength));
+
+ std::vector<uint8_t> message = GetBytesFromHexString(test, "message");
+ std::vector<uint8_t> signature = GetBytesFromHexString(test, "signature");
+
+ // Test that verification returns true when it should.
+ bool is_match = false;
+ ASSERT_EQ(Status::Success(),
+ Verify(CreateRsaPssAlgorithm(saltLength),
+ public_key,
+ CryptoData(signature),
+ CryptoData(message),
+ &is_match));
+ EXPECT_TRUE(is_match);
+
+ // Corrupt the message and make sure that verification fails.
+ ASSERT_EQ(Status::Success(),
+ Verify(CreateRsaPssAlgorithm(saltLength),
+ public_key,
+ CryptoData(signature),
+ CryptoData(Corrupted(message)),
+ &is_match));
+ EXPECT_FALSE(is_match);
+
+ // Corrupt the signature and make sure that verification fails.
+ ASSERT_EQ(Status::Success(),
+ Verify(CreateRsaPssAlgorithm(saltLength),
+ public_key,
+ CryptoData(Corrupted(signature)),
+ CryptoData(message),
+ &is_match));
+ EXPECT_FALSE(is_match);
+ }
+}
+
+} // namespace
+
+} // namespace webcrypto
+
+} // namespace content
« no previous file with comments | « content/child/webcrypto/platform_crypto.h ('k') | content/child/webcrypto/test/test_helpers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698