Commit 8793ece2 authored by eroman's avatar eroman Committed by Commit bot

[webcrypto] Implement RSA-PSS using BoringSSL.

BUG=399090

Review URL: https://codereview.chromium.org/661653002

Cr-Commit-Position: refs/heads/master@{#300327}
parent 5d0cfcac
...@@ -26,7 +26,8 @@ class AlgorithmRegistry { ...@@ -26,7 +26,8 @@ class AlgorithmRegistry {
aes_kw_(CreatePlatformAesKwImplementation()), aes_kw_(CreatePlatformAesKwImplementation()),
hmac_(CreatePlatformHmacImplementation()), hmac_(CreatePlatformHmacImplementation()),
rsa_ssa_(CreatePlatformRsaSsaImplementation()), rsa_ssa_(CreatePlatformRsaSsaImplementation()),
rsa_oaep_(CreatePlatformRsaOaepImplementation()) { rsa_oaep_(CreatePlatformRsaOaepImplementation()),
rsa_pss_(CreatePlatformRsaPssImplementation()) {
PlatformInit(); PlatformInit();
} }
...@@ -52,6 +53,8 @@ class AlgorithmRegistry { ...@@ -52,6 +53,8 @@ class AlgorithmRegistry {
return rsa_ssa_.get(); return rsa_ssa_.get();
case blink::WebCryptoAlgorithmIdRsaOaep: case blink::WebCryptoAlgorithmIdRsaOaep:
return rsa_oaep_.get(); return rsa_oaep_.get();
case blink::WebCryptoAlgorithmIdRsaPss:
return rsa_pss_.get();
default: default:
return NULL; return NULL;
} }
...@@ -66,6 +69,7 @@ class AlgorithmRegistry { ...@@ -66,6 +69,7 @@ class AlgorithmRegistry {
const scoped_ptr<AlgorithmImplementation> hmac_; const scoped_ptr<AlgorithmImplementation> hmac_;
const scoped_ptr<AlgorithmImplementation> rsa_ssa_; const scoped_ptr<AlgorithmImplementation> rsa_ssa_;
const scoped_ptr<AlgorithmImplementation> rsa_oaep_; const scoped_ptr<AlgorithmImplementation> rsa_oaep_;
const scoped_ptr<AlgorithmImplementation> rsa_pss_;
}; };
} // namespace } // namespace
......
...@@ -85,6 +85,11 @@ AlgorithmImplementation* CreatePlatformAesCtrImplementation() { ...@@ -85,6 +85,11 @@ AlgorithmImplementation* CreatePlatformAesCtrImplementation() {
return NULL; return NULL;
} }
AlgorithmImplementation* CreatePlatformRsaPssImplementation() {
// TODO(eroman): http://crbug.com/399090
return NULL;
}
} // namespace webcrypto } // namespace webcrypto
} // namespace content } // namespace content
// 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 "content/child/webcrypto/openssl/rsa_key_openssl.h"
#include "content/child/webcrypto/openssl/rsa_sign_openssl.h"
#include "content/child/webcrypto/status.h"
#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
namespace content {
namespace webcrypto {
namespace {
class RsaPssImplementation : public RsaHashedAlgorithm {
public:
RsaPssImplementation()
: RsaHashedAlgorithm(blink::WebCryptoKeyUsageVerify,
blink::WebCryptoKeyUsageSign) {}
virtual const char* GetJwkAlgorithm(
const blink::WebCryptoAlgorithmId hash) const override {
switch (hash) {
case blink::WebCryptoAlgorithmIdSha1:
return "PS1";
case blink::WebCryptoAlgorithmIdSha256:
return "PS256";
case blink::WebCryptoAlgorithmIdSha384:
return "PS384";
case blink::WebCryptoAlgorithmIdSha512:
return "PS512";
default:
return NULL;
}
}
virtual Status Sign(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
std::vector<uint8_t>* buffer) const override {
return RsaSign(
key, algorithm.rsaPssParams()->saltLengthBytes(), data, buffer);
}
virtual Status Verify(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& signature,
const CryptoData& data,
bool* signature_match) const override {
return RsaVerify(key,
algorithm.rsaPssParams()->saltLengthBytes(),
signature,
data,
signature_match);
}
};
} // namespace
AlgorithmImplementation* CreatePlatformRsaPssImplementation() {
return new RsaPssImplementation;
}
} // namespace webcrypto
} // namespace content
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/numerics/safe_math.h"
#include "content/child/webcrypto/crypto_data.h" #include "content/child/webcrypto/crypto_data.h"
#include "content/child/webcrypto/openssl/key_openssl.h" #include "content/child/webcrypto/openssl/key_openssl.h"
#include "content/child/webcrypto/openssl/rsa_key_openssl.h" #include "content/child/webcrypto/openssl/rsa_key_openssl.h"
...@@ -32,9 +33,42 @@ Status GetPKeyAndDigest(const blink::WebCryptoKey& key, ...@@ -32,9 +33,42 @@ Status GetPKeyAndDigest(const blink::WebCryptoKey& key,
return Status::Success(); return Status::Success();
} }
// Sets the PSS parameters on |pctx| if the key is for RSA-PSS.
//
// Otherwise returns Success without doing anything.
Status ApplyRsaPssOptions(const blink::WebCryptoKey& key,
const EVP_MD* const mgf_digest,
unsigned int salt_length_bytes,
EVP_PKEY_CTX* pctx) {
// Only apply RSA-PSS options if the key is for RSA-PSS.
if (key.algorithm().id() != blink::WebCryptoAlgorithmIdRsaPss) {
DCHECK_EQ(0u, salt_length_bytes);
DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, key.algorithm().id());
return Status::Success();
}
// BoringSSL takes a signed int for the salt length, and interprets
// negative values in a special manner. Make sure not to silently underflow.
base::CheckedNumeric<int> salt_length_bytes_int(salt_length_bytes);
if (!salt_length_bytes_int.IsValid()) {
// TODO(eroman): Give a better error message.
return Status::OperationError();
}
if (1 != EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
1 != EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf_digest) ||
1 != EVP_PKEY_CTX_set_rsa_pss_saltlen(
pctx, salt_length_bytes_int.ValueOrDie())) {
return Status::OperationError();
}
return Status::Success();
}
} // namespace } // namespace
Status RsaSign(const blink::WebCryptoKey& key, Status RsaSign(const blink::WebCryptoKey& key,
unsigned int pss_salt_length_bytes,
const CryptoData& data, const CryptoData& data,
std::vector<uint8_t>* buffer) { std::vector<uint8_t>* buffer) {
if (key.type() != blink::WebCryptoKeyTypePrivate) if (key.type() != blink::WebCryptoKeyTypePrivate)
...@@ -42,6 +76,7 @@ Status RsaSign(const blink::WebCryptoKey& key, ...@@ -42,6 +76,7 @@ Status RsaSign(const blink::WebCryptoKey& key,
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create()); crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
EVP_PKEY_CTX* pctx = NULL; // Owned by |ctx|.
EVP_PKEY* private_key = NULL; EVP_PKEY* private_key = NULL;
const EVP_MD* digest = NULL; const EVP_MD* digest = NULL;
...@@ -54,8 +89,16 @@ Status RsaSign(const blink::WebCryptoKey& key, ...@@ -54,8 +89,16 @@ Status RsaSign(const blink::WebCryptoKey& key,
// the real one, which may be smaller. // the real one, which may be smaller.
size_t sig_len = 0; size_t sig_len = 0;
if (!ctx.get() || if (!ctx.get() ||
!EVP_DigestSignInit(ctx.get(), NULL, digest, NULL, private_key) || !EVP_DigestSignInit(ctx.get(), &pctx, digest, NULL, private_key)) {
!EVP_DigestSignUpdate(ctx.get(), data.bytes(), data.byte_length()) || return Status::OperationError();
}
// Set PSS-specific options (if applicable).
status = ApplyRsaPssOptions(key, digest, pss_salt_length_bytes, pctx);
if (status.IsError())
return status;
if (!EVP_DigestSignUpdate(ctx.get(), data.bytes(), data.byte_length()) ||
!EVP_DigestSignFinal(ctx.get(), NULL, &sig_len)) { !EVP_DigestSignFinal(ctx.get(), NULL, &sig_len)) {
return Status::OperationError(); return Status::OperationError();
} }
...@@ -69,6 +112,7 @@ Status RsaSign(const blink::WebCryptoKey& key, ...@@ -69,6 +112,7 @@ Status RsaSign(const blink::WebCryptoKey& key,
} }
Status RsaVerify(const blink::WebCryptoKey& key, Status RsaVerify(const blink::WebCryptoKey& key,
unsigned int pss_salt_length_bytes,
const CryptoData& signature, const CryptoData& signature,
const CryptoData& data, const CryptoData& data,
bool* signature_match) { bool* signature_match) {
...@@ -77,6 +121,7 @@ Status RsaVerify(const blink::WebCryptoKey& key, ...@@ -77,6 +121,7 @@ Status RsaVerify(const blink::WebCryptoKey& key,
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create()); crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
EVP_PKEY_CTX* pctx = NULL; // Owned by |ctx|.
EVP_PKEY* public_key = NULL; EVP_PKEY* public_key = NULL;
const EVP_MD* digest = NULL; const EVP_MD* digest = NULL;
...@@ -84,9 +129,14 @@ Status RsaVerify(const blink::WebCryptoKey& key, ...@@ -84,9 +129,14 @@ Status RsaVerify(const blink::WebCryptoKey& key,
if (status.IsError()) if (status.IsError())
return status; return status;
if (!EVP_DigestVerifyInit(ctx.get(), NULL, digest, NULL, public_key)) if (!EVP_DigestVerifyInit(ctx.get(), &pctx, digest, NULL, public_key))
return Status::OperationError(); return Status::OperationError();
// Set PSS-specific options (if applicable).
status = ApplyRsaPssOptions(key, digest, pss_salt_length_bytes, pctx);
if (status.IsError())
return status;
if (!EVP_DigestVerifyUpdate(ctx.get(), data.bytes(), data.byte_length())) if (!EVP_DigestVerifyUpdate(ctx.get(), data.bytes(), data.byte_length()))
return Status::OperationError(); return Status::OperationError();
......
...@@ -20,13 +20,19 @@ namespace webcrypto { ...@@ -20,13 +20,19 @@ namespace webcrypto {
class CryptoData; class CryptoData;
class Status; class Status;
// Helper functions for doing RSA-SSA signing and verification. // Helper functions for doing RSA-SSA signing and verification
// (both PKCS1-v1_5 and PSS flavor).
//
// The salt length parameter is only relevant when the key is for RSA-PSS. In
// other cases it should be set to zero.
Status RsaSign(const blink::WebCryptoKey& key, Status RsaSign(const blink::WebCryptoKey& key,
unsigned int pss_salt_length_bytes,
const CryptoData& data, const CryptoData& data,
std::vector<uint8_t>* buffer); std::vector<uint8_t>* buffer);
Status RsaVerify(const blink::WebCryptoKey& key, Status RsaVerify(const blink::WebCryptoKey& key,
unsigned int pss_salt_length_bytes,
const CryptoData& signature, const CryptoData& signature,
const CryptoData& data, const CryptoData& data,
bool* signature_match); bool* signature_match);
......
...@@ -38,7 +38,7 @@ class RsaSsaImplementation : public RsaHashedAlgorithm { ...@@ -38,7 +38,7 @@ class RsaSsaImplementation : public RsaHashedAlgorithm {
const blink::WebCryptoKey& key, const blink::WebCryptoKey& key,
const CryptoData& data, const CryptoData& data,
std::vector<uint8_t>* buffer) const override { std::vector<uint8_t>* buffer) const override {
return RsaSign(key, data, buffer); return RsaSign(key, 0, data, buffer);
} }
virtual Status Verify(const blink::WebCryptoAlgorithm& algorithm, virtual Status Verify(const blink::WebCryptoAlgorithm& algorithm,
...@@ -46,7 +46,7 @@ class RsaSsaImplementation : public RsaHashedAlgorithm { ...@@ -46,7 +46,7 @@ class RsaSsaImplementation : public RsaHashedAlgorithm {
const CryptoData& signature, const CryptoData& signature,
const CryptoData& data, const CryptoData& data,
bool* signature_match) const override { bool* signature_match) const override {
return RsaVerify(key, signature, data, signature_match); return RsaVerify(key, 0, signature, data, signature_match);
} }
}; };
......
...@@ -31,6 +31,7 @@ AlgorithmImplementation* CreatePlatformAesKwImplementation(); ...@@ -31,6 +31,7 @@ AlgorithmImplementation* CreatePlatformAesKwImplementation();
AlgorithmImplementation* CreatePlatformHmacImplementation(); AlgorithmImplementation* CreatePlatformHmacImplementation();
AlgorithmImplementation* CreatePlatformRsaOaepImplementation(); AlgorithmImplementation* CreatePlatformRsaOaepImplementation();
AlgorithmImplementation* CreatePlatformRsaSsaImplementation(); AlgorithmImplementation* CreatePlatformRsaSsaImplementation();
AlgorithmImplementation* CreatePlatformRsaPssImplementation();
bool PlatformSerializeKeyForClone(const blink::WebCryptoKey& key, bool PlatformSerializeKeyForClone(const blink::WebCryptoKey& key,
blink::WebVector<uint8_t>* key_data); blink::WebVector<uint8_t>* key_data);
......
This diff is collapsed.
...@@ -121,8 +121,6 @@ blink::WebCryptoAlgorithm CreateRsaHashedKeyGenAlgorithm( ...@@ -121,8 +121,6 @@ blink::WebCryptoAlgorithm CreateRsaHashedKeyGenAlgorithm(
const blink::WebCryptoAlgorithmId hash_id, const blink::WebCryptoAlgorithmId hash_id,
unsigned int modulus_length, unsigned int modulus_length,
const std::vector<uint8_t>& public_exponent) { const std::vector<uint8_t>& public_exponent) {
DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep);
DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id)); DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id));
return blink::WebCryptoAlgorithm::adoptParamsAndCreate( return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
algorithm_id, algorithm_id,
...@@ -206,8 +204,28 @@ std::vector<uint8_t> MakeJsonVector(const base::DictionaryValue& dict) { ...@@ -206,8 +204,28 @@ std::vector<uint8_t> MakeJsonVector(const base::DictionaryValue& dict) {
return ::testing::AssertionSuccess(); return ::testing::AssertionSuccess();
} }
std::vector<uint8_t> GetBytesFromHexString(base::DictionaryValue* dict, ::testing::AssertionResult ReadJsonTestFileToDictionary(
const char* property_name) { const char* test_file_name,
scoped_ptr<base::DictionaryValue>* dict) {
// Read the JSON.
scoped_ptr<base::Value> json;
::testing::AssertionResult result = ReadJsonTestFile(test_file_name, &json);
if (!result)
return result;
// Cast to an DictionaryValue.
base::DictionaryValue* dict_value = NULL;
if (!json->GetAsDictionary(&dict_value) || !dict_value)
return ::testing::AssertionFailure() << "The JSON was not a dictionary";
dict->reset(dict_value);
ignore_result(json.release());
return ::testing::AssertionSuccess();
}
std::vector<uint8_t> GetBytesFromHexString(const base::DictionaryValue* dict,
const std::string& property_name) {
std::string hex_string; std::string hex_string;
if (!dict->GetString(property_name, &hex_string)) { if (!dict->GetString(property_name, &hex_string)) {
EXPECT_TRUE(false) << "Couldn't get string property: " << property_name; EXPECT_TRUE(false) << "Couldn't get string property: " << property_name;
...@@ -217,7 +235,7 @@ std::vector<uint8_t> GetBytesFromHexString(base::DictionaryValue* dict, ...@@ -217,7 +235,7 @@ std::vector<uint8_t> GetBytesFromHexString(base::DictionaryValue* dict,
return HexStringToBytes(hex_string); return HexStringToBytes(hex_string);
} }
blink::WebCryptoAlgorithm GetDigestAlgorithm(base::DictionaryValue* dict, blink::WebCryptoAlgorithm GetDigestAlgorithm(const base::DictionaryValue* dict,
const char* property_name) { const char* property_name) {
std::string algorithm_name; std::string algorithm_name;
if (!dict->GetString(property_name, &algorithm_name)) { if (!dict->GetString(property_name, &algorithm_name)) {
......
...@@ -83,18 +83,22 @@ std::vector<uint8_t> MakeJsonVector(const base::DictionaryValue& dict); ...@@ -83,18 +83,22 @@ std::vector<uint8_t> MakeJsonVector(const base::DictionaryValue& dict);
::testing::AssertionResult ReadJsonTestFileToList( ::testing::AssertionResult ReadJsonTestFileToList(
const char* test_file_name, const char* test_file_name,
scoped_ptr<base::ListValue>* list); scoped_ptr<base::ListValue>* list);
// Same as ReadJsonTestFile(), but returns the value as a Dictionary.
::testing::AssertionResult ReadJsonTestFileToDictionary(
const char* test_file_name,
scoped_ptr<base::DictionaryValue>* dict);
// Reads a string property from the dictionary with path |property_name| // Reads a string property from the dictionary with path |property_name|
// (which can include periods for nested dictionaries). Interprets the // (which can include periods for nested dictionaries). Interprets the
// string as a hex encoded string and converts it to a bytes list. // string as a hex encoded string and converts it to a bytes list.
// //
// Returns empty vector on failure. // Returns empty vector on failure.
std::vector<uint8_t> GetBytesFromHexString(base::DictionaryValue* dict, std::vector<uint8_t> GetBytesFromHexString(const base::DictionaryValue* dict,
const char* property_name); const std::string& property_name);
// Reads a string property with path "property_name" and converts it to a // Reads a string property with path "property_name" and converts it to a
// WebCryptoAlgorith. Returns null algorithm on failure. // WebCryptoAlgorith. Returns null algorithm on failure.
blink::WebCryptoAlgorithm GetDigestAlgorithm(base::DictionaryValue* dict, blink::WebCryptoAlgorithm GetDigestAlgorithm(const base::DictionaryValue* dict,
const char* property_name); const char* property_name);
// Returns true if any of the vectors in the input list have identical content. // Returns true if any of the vectors in the input list have identical content.
......
...@@ -118,8 +118,6 @@ blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm( ...@@ -118,8 +118,6 @@ blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm(
blink::WebCryptoAlgorithmId id, blink::WebCryptoAlgorithmId id,
blink::WebCryptoAlgorithmId hash_id) { blink::WebCryptoAlgorithmId hash_id) {
DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id)); DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id));
DCHECK(id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
id == blink::WebCryptoAlgorithmIdRsaOaep);
return blink::WebCryptoAlgorithm::adoptParamsAndCreate( return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
id, new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id))); id, new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id)));
} }
...@@ -137,7 +135,8 @@ bool KeyUsageAllows(const blink::WebCryptoKey& key, ...@@ -137,7 +135,8 @@ bool KeyUsageAllows(const blink::WebCryptoKey& key,
bool IsAlgorithmRsa(blink::WebCryptoAlgorithmId alg_id) { bool IsAlgorithmRsa(blink::WebCryptoAlgorithmId alg_id) {
return alg_id == blink::WebCryptoAlgorithmIdRsaOaep || return alg_id == blink::WebCryptoAlgorithmIdRsaOaep ||
alg_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; alg_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
alg_id == blink::WebCryptoAlgorithmIdRsaPss;
} }
// The WebCrypto spec defines the default value for the tag length, as well as // The WebCrypto spec defines the default value for the tag length, as well as
......
...@@ -286,6 +286,7 @@ ...@@ -286,6 +286,7 @@
'child/webcrypto/openssl/rsa_key_openssl.cc', 'child/webcrypto/openssl/rsa_key_openssl.cc',
'child/webcrypto/openssl/rsa_key_openssl.h', 'child/webcrypto/openssl/rsa_key_openssl.h',
'child/webcrypto/openssl/rsa_oaep_openssl.cc', 'child/webcrypto/openssl/rsa_oaep_openssl.cc',
'child/webcrypto/openssl/rsa_pss_openssl.cc',
'child/webcrypto/openssl/rsa_sign_openssl.cc', 'child/webcrypto/openssl/rsa_sign_openssl.cc',
'child/webcrypto/openssl/rsa_sign_openssl.h', 'child/webcrypto/openssl/rsa_sign_openssl.h',
'child/webcrypto/openssl/rsa_ssa_openssl.cc', 'child/webcrypto/openssl/rsa_ssa_openssl.cc',
......
...@@ -652,11 +652,12 @@ ...@@ -652,11 +652,12 @@
'child/webcrypto/test/aes_ctr_unittest.cc', 'child/webcrypto/test/aes_ctr_unittest.cc',
'child/webcrypto/test/aes_gcm_unittest.cc', 'child/webcrypto/test/aes_gcm_unittest.cc',
'child/webcrypto/test/aes_kw_unittest.cc', 'child/webcrypto/test/aes_kw_unittest.cc',
'child/webcrypto/test/status_unittest.cc',
'child/webcrypto/test/hmac_unittest.cc', 'child/webcrypto/test/hmac_unittest.cc',
'child/webcrypto/test/rsa_oaep_unittest.cc', 'child/webcrypto/test/rsa_oaep_unittest.cc',
'child/webcrypto/test/rsa_pss_unittest.cc',
'child/webcrypto/test/rsa_ssa_unittest.cc', 'child/webcrypto/test/rsa_ssa_unittest.cc',
'child/webcrypto/test/sha_unittest.cc', 'child/webcrypto/test/sha_unittest.cc',
'child/webcrypto/test/status_unittest.cc',
'child/webcrypto/test/test_helpers.cc', 'child/webcrypto/test/test_helpers.cc',
'child/webcrypto/test/test_helpers.h', 'child/webcrypto/test/test_helpers.h',
'child/worker_task_runner_unittest.cc', 'child/worker_task_runner_unittest.cc',
......
{
// This contains known answer tests for verify operation of RSA-PSS (all are successes).
// The keys are in SPKI format.
"keys": {
"key1": "30819F300D06092A864886F70D010101050003818D0030818902818100A56E4A0E701017589A5187DC7EA841D156F2EC0E36AD52A44DFEB1E61F7AD991D8C51056FFEDB162B4C0F283A12A88A394DFF526AB7291CBB307CEABFCE0B1DFD5CD9508096D5B2B8B6DF5D671EF6377C0921CB23C270A70E2598E6FF89D19F105ACC2D3F0CB35F29280E1386B6F64C4EF22E1E1F20D0CE8CFFB2249BD9A21370203010001",
"key2": "30819D300D06092A864886F70D010101050003818B0030818702818100BE499B5E7F06C83FA0293E31465C8EB6B58AF920BAE52A7B5B9BFEB7AA72DB1264112EB3FD431D31A2A7E50941566929494A0E891ED5613918B4B51B0D1FB97783B26ACF7D0F384CFB35F4D2824F5DD380623A26BF180B63961C619DCDB20CAE406F22F6E276C80A37259490CFEB72C1A71A84F1846D330877BA3E3101EC9C7B020111"
},
"tests": [
// Example 1.1 from
// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip (pss-vect.txt)
{
"hash": "sha-1",
"key": "key1",
"message": "cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0",
"saltLength": 20,
"signature": "9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c"
},
// Example 1.4 from
// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip (pss-vect.txt)
{
"hash": "sha-1",
"key": "key1",
"message": "bc656747fa9eafb3f0",
"saltLength": 20,
"signature": "4609793b23e9d09362dc21bb47da0b4f3a7622649a47d464019b9aeafe53359c178c91cd58ba6bcb78be0346a7bc637f4b873d4bab38ee661f199634c547a1ad8442e03da015b136e543f7ab07c0c13e4225b8de8cce25d4f6eb8400f81f7e1833b7ee6e334d370964ca79fdb872b4d75223b5eeb08101591fb532d155a6de87"
},
// http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-2rsatestvectors.zip (SigVerPSS_186-3.rsp)
{
"hash": "sha-256",
"key": "key2",
"message": "c7f5270fca725f9bd19f519a8d7cca3cc5c079024029f3bae510f9b02140fe238908e4f6c18f07a89c687c8684669b1f1db2baf9251a3c829faccb493084e16ec9e28d58868074a5d6221667dd6e528d16fe2c9f3db4cfaf6c4dce8c8439af38ceaaaa9ce2ecae7bc8f4a5a55e3bf96df9cd575c4f9cb327951b8cdfe4087168",
"saltLength": 10,
"signature": "11e169f2fd40b07641b9768a2ab19965fb6c27f10fcf0323fcc6d12eb4f1c06b330ddaa1ea504407afa29de9ebe0374fe9d1e7d0ffbd5fc1cf3a3446e4145415d2ab24f789b3464c5c43a256bbc1d692cf7f04801dac5bb401a4a03ab7d5728a860c19e1a4dc797ca542c8203cec2e601eb0c51f567f2eda022b0b9ebddeeefa"
},
// http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-2rsatestvectors.zip (SigVerPSS_186-3.rsp)
{
"hash": "sha-384",
"key": "key2",
"message": "c7f5270fca725f9bd19f519a8d7cca3cc5c079024029f3bae510f9b02140fe238908e4f6c18f07a89c687c8684669b1f1db2baf9251a3c829faccb493084e16ec9e28d58868074a5d6221667dd6e528d16fe2c9f3db4cfaf6c4dce8c8439af38ceaaaa9ce2ecae7bc8f4a5a55e3bf96df9cd575c4f9cb327951b8cdfe4087168",
"saltLength": 10,
"signature": "b281ad934b2775c0cba5fb10aa574d2ed85c7f99b942b78e49702480069362ed394baded55e56cfcbe7b0b8d2217a05a60e1acd725cb09060dfac585bc2132b99b41cdbd530c69d17cdbc84bc6b9830fc7dc8e1b2412cfe06dcf8c1a0cc3453f93f25ebf10cb0c90334fac573f449138616e1a194c67f44efac34cc07a526267"
},
// http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-2rsatestvectors.zip (SigVerPSS_186-3.rsp)
{
"hash": "sha-512",
"key": "key2",
"message": "c7f5270fca725f9bd19f519a8d7cca3cc5c079024029f3bae510f9b02140fe238908e4f6c18f07a89c687c8684669b1f1db2baf9251a3c829faccb493084e16ec9e28d58868074a5d6221667dd6e528d16fe2c9f3db4cfaf6c4dce8c8439af38ceaaaa9ce2ecae7bc8f4a5a55e3bf96df9cd575c4f9cb327951b8cdfe4087168",
"saltLength": 10,
"signature": "8ffc38f9b820ef6b080fd2ec7de5626c658d79056f3edf610a295b7b0546f73e01ffdf4d0070ebf79c33fd86c2d608be9438b3d420d09535b97cd3d846ecaf8f6551cdf93197e9f8fb048044473ab41a801e9f7fc983c62b324361dade9f71a65952bd35c59faaa4d6ff462f68a6c4ec0b428aa47336f2178aeb276136563b7d"
}
]
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment