Skip to content

Commit

Permalink
Introduce RSAPrivateKey::SignDigest
Browse files Browse the repository at this point in the history
BUG=258017
R=rsleevi@chromium.org

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@210524 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
pfeldman@chromium.org committed Jul 9, 2013
1 parent 0061349 commit ed31834
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 6 deletions.
7 changes: 7 additions & 0 deletions crypto/signature_creator.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ class CRYPTO_EXPORT SignatureCreator {
// instance outlives the created SignatureCreator.
static SignatureCreator* Create(RSAPrivateKey* key);

// Signs the precomputed SHA-1 digest |data| using private |key| as
// specified in PKCS #1 v1.5.
static bool Sign(RSAPrivateKey* key,
const uint8* data,
int data_len,
std::vector<uint8>* signature);

// Update the signature with more data.
bool Update(const uint8* data_part, int data_part_len);

Expand Down
23 changes: 23 additions & 0 deletions crypto/signature_creator_nss.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,29 @@ SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) {
return result.release();
}

// static
bool SignatureCreator::Sign(RSAPrivateKey* key,
const uint8* data,
int data_len,
std::vector<uint8>* signature) {
SECItem data_item;
data_item.type = siBuffer;
data_item.data = const_cast<unsigned char*>(data);
data_item.len = data_len;

SECItem signature_item;
SECStatus rv = SGN_Digest(key->key(), SEC_OID_SHA1, &signature_item,
&data_item);
if (rv != SECSuccess) {
NOTREACHED();
return false;
}
signature->assign(signature_item.data,
signature_item.data + signature_item.len);
SECITEM_FreeItem(&signature_item, PR_FALSE);
return true;
}

bool SignatureCreator::Update(const uint8* data_part, int data_part_len) {
// TODO(wtc): Remove this const_cast when we require NSS 3.12.5.
// See NSS bug https://bugzilla.mozilla.org/show_bug.cgi?id=518255
Expand Down
22 changes: 22 additions & 0 deletions crypto/signature_creator_openssl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "crypto/signature_creator.h"

#include <openssl/evp.h>
#include <openssl/rsa.h>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
Expand All @@ -24,6 +25,27 @@ SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) {
return result.release();
}

// static
bool SignatureCreator::Sign(RSAPrivateKey* key,
const uint8* data,
int data_len,
std::vector<uint8>* signature) {
RSA* rsa_key = EVP_PKEY_get1_RSA(key->key());
if (!rsa_key)
return false;
signature->resize(RSA_size(rsa_key));

unsigned int len = 0;
bool success = RSA_sign(NID_sha1, data, data_len, vector_as_array(signature),
&len, rsa_key);
if (!success) {
signature->clear();
return false;
}
signature->resize(len);
return true;
}

SignatureCreator::SignatureCreator()
: sign_context_(EVP_MD_CTX_create()) {
}
Expand Down
54 changes: 48 additions & 6 deletions crypto/signature_creator_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,22 @@
#include <vector>

#include "base/memory/scoped_ptr.h"
#include "base/sha1.h"
#include "crypto/rsa_private_key.h"
#include "crypto/signature_creator.h"
#include "crypto/signature_verifier.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

// This is the algorithm ID for SHA-1 with RSA encryption.
const uint8 kSHA1WithRSAAlgorithmID[] = {
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00
};

}

TEST(SignatureCreatorTest, BasicTest) {
// Do a verify round trip.
scoped_ptr<crypto::RSAPrivateKey> key_original(
Expand All @@ -36,12 +47,43 @@ TEST(SignatureCreatorTest, BasicTest) {
std::vector<uint8> public_key_info;
ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info));

// This is the algorithm ID for SHA-1 with RSA encryption.
// TODO(aa): Factor this out into some shared location.
const uint8 kSHA1WithRSAAlgorithmID[] = {
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00
};
crypto::SignatureVerifier verifier;
ASSERT_TRUE(verifier.VerifyInit(
kSHA1WithRSAAlgorithmID, sizeof(kSHA1WithRSAAlgorithmID),
&signature.front(), signature.size(),
&public_key_info.front(), public_key_info.size()));

verifier.VerifyUpdate(reinterpret_cast<const uint8*>(data.c_str()),
data.size());
ASSERT_TRUE(verifier.VerifyFinal());
}

TEST(SignatureCreatorTest, SignDigestTest) {
// Do a verify round trip.
scoped_ptr<crypto::RSAPrivateKey> key_original(
crypto::RSAPrivateKey::Create(1024));
ASSERT_TRUE(key_original.get());

std::vector<uint8> key_info;
key_original->ExportPrivateKey(&key_info);
scoped_ptr<crypto::RSAPrivateKey> key(
crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info));
ASSERT_TRUE(key.get());

std::string data("Hello, World!");
std::string sha1 = base::SHA1HashString(data);
// Sign sha1 of the input data.
std::vector<uint8> signature;
ASSERT_TRUE(crypto::SignatureCreator::Sign(
key.get(),
reinterpret_cast<const uint8*>(sha1.c_str()),
sha1.size(),
&signature));

std::vector<uint8> public_key_info;
ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info));

// Verify the input data.
crypto::SignatureVerifier verifier;
ASSERT_TRUE(verifier.VerifyInit(
kSHA1WithRSAAlgorithmID, sizeof(kSHA1WithRSAAlgorithmID),
Expand Down

0 comments on commit ed31834

Please sign in to comment.