Index: crypto/rsa_private_key_nss.cc |
diff --git a/crypto/rsa_private_key_nss.cc b/crypto/rsa_private_key_nss.cc |
deleted file mode 100644 |
index 2538a723ae4b8b05f768aadea5611ec61b3593b0..0000000000000000000000000000000000000000 |
--- a/crypto/rsa_private_key_nss.cc |
+++ /dev/null |
@@ -1,633 +0,0 @@ |
-// Copyright (c) 2011 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 "crypto/rsa_private_key.h" |
- |
-#include <cryptohi.h> |
-#include <keyhi.h> |
-#include <pk11pub.h> |
-#include <stdint.h> |
- |
-#include <list> |
-#include <memory> |
- |
-#include "base/debug/leak_annotations.h" |
-#include "base/logging.h" |
-#include "base/strings/string_util.h" |
-#include "crypto/nss_key_util.h" |
-#include "crypto/nss_util.h" |
-#include "crypto/scoped_nss_types.h" |
- |
-// Helper for error handling during key import. |
-#define READ_ASSERT(truth) \ |
- if (!(truth)) { \ |
- NOTREACHED(); \ |
- return false; \ |
- } |
- |
-// TODO(rafaelw): Consider using NSS's ASN.1 encoder. |
-namespace { |
- |
-static bool ReadAttribute(SECKEYPrivateKey* key, |
- CK_ATTRIBUTE_TYPE type, |
- std::vector<uint8_t>* output) { |
- SECItem item; |
- SECStatus rv; |
- rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item); |
- if (rv != SECSuccess) { |
- NOTREACHED(); |
- return false; |
- } |
- |
- output->assign(item.data, item.data + item.len); |
- SECITEM_FreeItem(&item, PR_FALSE); |
- return true; |
-} |
- |
-// Used internally by RSAPrivateKey for serializing and deserializing |
-// PKCS #8 PrivateKeyInfo and PublicKeyInfo. |
-class PrivateKeyInfoCodec { |
- public: |
- // ASN.1 encoding of the AlgorithmIdentifier from PKCS #8. |
- static const uint8_t kRsaAlgorithmIdentifier[]; |
- |
- // ASN.1 tags for some types we use. |
- static const uint8_t kBitStringTag = 0x03; |
- static const uint8_t kIntegerTag = 0x02; |
- static const uint8_t kOctetStringTag = 0x04; |
- static const uint8_t kSequenceTag = 0x30; |
- |
- // |big_endian| here specifies the byte-significance of the integer components |
- // that will be parsed & serialized (modulus(), etc...) during Import(), |
- // Export() and ExportPublicKeyInfo() -- not the ASN.1 DER encoding of the |
- // PrivateKeyInfo/PublicKeyInfo (which is always big-endian). |
- explicit PrivateKeyInfoCodec(bool big_endian); |
- |
- ~PrivateKeyInfoCodec(); |
- |
- // Exports the contents of the integer components to the ASN.1 DER encoding |
- // of the PrivateKeyInfo structure to |output|. |
- bool Export(std::vector<uint8_t>* output); |
- |
- // Exports the contents of the integer components to the ASN.1 DER encoding |
- // of the PublicKeyInfo structure to |output|. |
- bool ExportPublicKeyInfo(std::vector<uint8_t>* output); |
- |
- // Exports the contents of the integer components to the ASN.1 DER encoding |
- // of the RSAPublicKey structure to |output|. |
- bool ExportPublicKey(std::vector<uint8_t>* output); |
- |
- // Parses the ASN.1 DER encoding of the PrivateKeyInfo structure in |input| |
- // and populates the integer components with |big_endian_| byte-significance. |
- // IMPORTANT NOTE: This is currently *not* security-approved for importing |
- // keys from unstrusted sources. |
- bool Import(const std::vector<uint8_t>& input); |
- |
- // Accessors to the contents of the integer components of the PrivateKeyInfo |
- // structure. |
- std::vector<uint8_t>* modulus() { return &modulus_; } |
- std::vector<uint8_t>* public_exponent() { return &public_exponent_; } |
- std::vector<uint8_t>* private_exponent() { return &private_exponent_; } |
- std::vector<uint8_t>* prime1() { return &prime1_; } |
- std::vector<uint8_t>* prime2() { return &prime2_; } |
- std::vector<uint8_t>* exponent1() { return &exponent1_; } |
- std::vector<uint8_t>* exponent2() { return &exponent2_; } |
- std::vector<uint8_t>* coefficient() { return &coefficient_; } |
- |
- private: |
- // Utility wrappers for PrependIntegerImpl that use the class's |big_endian_| |
- // value. |
- void PrependInteger(const std::vector<uint8_t>& in, std::list<uint8_t>* out); |
- void PrependInteger(uint8_t* val, int num_bytes, std::list<uint8_t>* data); |
- |
- // Prepends the integer stored in |val| - |val + num_bytes| with |big_endian| |
- // byte-significance into |data| as an ASN.1 integer. |
- void PrependIntegerImpl(uint8_t* val, |
- int num_bytes, |
- std::list<uint8_t>* data, |
- bool big_endian); |
- |
- // Utility wrappers for ReadIntegerImpl that use the class's |big_endian_| |
- // value. |
- bool ReadInteger(uint8_t** pos, uint8_t* end, std::vector<uint8_t>* out); |
- bool ReadIntegerWithExpectedSize(uint8_t** pos, |
- uint8_t* end, |
- size_t expected_size, |
- std::vector<uint8_t>* out); |
- |
- // Reads an ASN.1 integer from |pos|, and stores the result into |out| with |
- // |big_endian| byte-significance. |
- bool ReadIntegerImpl(uint8_t** pos, |
- uint8_t* end, |
- std::vector<uint8_t>* out, |
- bool big_endian); |
- |
- // Prepends the integer stored in |val|, starting a index |start|, for |
- // |num_bytes| bytes onto |data|. |
- void PrependBytes(uint8_t* val, |
- int start, |
- int num_bytes, |
- std::list<uint8_t>* data); |
- |
- // Helper to prepend an ASN.1 length field. |
- void PrependLength(size_t size, std::list<uint8_t>* data); |
- |
- // Helper to prepend an ASN.1 type header. |
- void PrependTypeHeaderAndLength(uint8_t type, |
- uint32_t length, |
- std::list<uint8_t>* output); |
- |
- // Helper to prepend an ASN.1 bit string |
- void PrependBitString(uint8_t* val, |
- int num_bytes, |
- std::list<uint8_t>* output); |
- |
- // Read an ASN.1 length field. This also checks that the length does not |
- // extend beyond |end|. |
- bool ReadLength(uint8_t** pos, uint8_t* end, uint32_t* result); |
- |
- // Read an ASN.1 type header and its length. |
- bool ReadTypeHeaderAndLength(uint8_t** pos, |
- uint8_t* end, |
- uint8_t expected_tag, |
- uint32_t* length); |
- |
- // Read an ASN.1 sequence declaration. This consumes the type header and |
- // length field, but not the contents of the sequence. |
- bool ReadSequence(uint8_t** pos, uint8_t* end); |
- |
- // Read the RSA AlgorithmIdentifier. |
- bool ReadAlgorithmIdentifier(uint8_t** pos, uint8_t* end); |
- |
- // Read one of the two version fields in PrivateKeyInfo. |
- bool ReadVersion(uint8_t** pos, uint8_t* end); |
- |
- // The byte-significance of the stored components (modulus, etc..). |
- bool big_endian_; |
- |
- // Component integers of the PrivateKeyInfo |
- std::vector<uint8_t> modulus_; |
- std::vector<uint8_t> public_exponent_; |
- std::vector<uint8_t> private_exponent_; |
- std::vector<uint8_t> prime1_; |
- std::vector<uint8_t> prime2_; |
- std::vector<uint8_t> exponent1_; |
- std::vector<uint8_t> exponent2_; |
- std::vector<uint8_t> coefficient_; |
- |
- DISALLOW_COPY_AND_ASSIGN(PrivateKeyInfoCodec); |
-}; |
- |
-const uint8_t PrivateKeyInfoCodec::kRsaAlgorithmIdentifier[] = { |
- 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, |
- 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00}; |
- |
-PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian) |
- : big_endian_(big_endian) {} |
- |
-PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {} |
- |
-bool PrivateKeyInfoCodec::Export(std::vector<uint8_t>* output) { |
- std::list<uint8_t> content; |
- |
- // Version (always zero) |
- uint8_t version = 0; |
- |
- PrependInteger(coefficient_, &content); |
- PrependInteger(exponent2_, &content); |
- PrependInteger(exponent1_, &content); |
- PrependInteger(prime2_, &content); |
- PrependInteger(prime1_, &content); |
- PrependInteger(private_exponent_, &content); |
- PrependInteger(public_exponent_, &content); |
- PrependInteger(modulus_, &content); |
- PrependInteger(&version, 1, &content); |
- PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); |
- PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content); |
- |
- // RSA algorithm OID |
- for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i) |
- content.push_front(kRsaAlgorithmIdentifier[i - 1]); |
- |
- PrependInteger(&version, 1, &content); |
- PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); |
- |
- // Copy everying into the output. |
- output->reserve(content.size()); |
- output->assign(content.begin(), content.end()); |
- |
- return true; |
-} |
- |
-bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8_t>* output) { |
- // Create a sequence with the modulus (n) and public exponent (e). |
- std::vector<uint8_t> bit_string; |
- if (!ExportPublicKey(&bit_string)) |
- return false; |
- |
- // Add the sequence as the contents of a bit string. |
- std::list<uint8_t> content; |
- PrependBitString(&bit_string[0], static_cast<int>(bit_string.size()), |
- &content); |
- |
- // Add the RSA algorithm OID. |
- for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i) |
- content.push_front(kRsaAlgorithmIdentifier[i - 1]); |
- |
- // Finally, wrap everything in a sequence. |
- PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); |
- |
- // Copy everything into the output. |
- output->reserve(content.size()); |
- output->assign(content.begin(), content.end()); |
- |
- return true; |
-} |
- |
-bool PrivateKeyInfoCodec::ExportPublicKey(std::vector<uint8_t>* output) { |
- // Create a sequence with the modulus (n) and public exponent (e). |
- std::list<uint8_t> content; |
- PrependInteger(&public_exponent_[0], |
- static_cast<int>(public_exponent_.size()), |
- &content); |
- PrependInteger(&modulus_[0], static_cast<int>(modulus_.size()), &content); |
- PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); |
- |
- // Copy everything into the output. |
- output->reserve(content.size()); |
- output->assign(content.begin(), content.end()); |
- |
- return true; |
-} |
- |
-bool PrivateKeyInfoCodec::Import(const std::vector<uint8_t>& input) { |
- if (input.empty()) { |
- return false; |
- } |
- |
- // Parse the private key info up to the public key values, ignoring |
- // the subsequent private key values. |
- uint8_t* src = const_cast<uint8_t*>(&input.front()); |
- uint8_t* end = src + input.size(); |
- if (!ReadSequence(&src, end) || |
- !ReadVersion(&src, end) || |
- !ReadAlgorithmIdentifier(&src, end) || |
- !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) || |
- !ReadSequence(&src, end) || |
- !ReadVersion(&src, end) || |
- !ReadInteger(&src, end, &modulus_)) |
- return false; |
- |
- int mod_size = modulus_.size(); |
- READ_ASSERT(mod_size % 2 == 0); |
- int primes_size = mod_size / 2; |
- |
- if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent_) || |
- !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent_) || |
- !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1_) || |
- !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2_) || |
- !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1_) || |
- !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2_) || |
- !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient_)) |
- return false; |
- |
- READ_ASSERT(src == end); |
- |
- |
- return true; |
-} |
- |
-void PrivateKeyInfoCodec::PrependInteger(const std::vector<uint8_t>& in, |
- std::list<uint8_t>* out) { |
- uint8_t* ptr = const_cast<uint8_t*>(&in.front()); |
- PrependIntegerImpl(ptr, in.size(), out, big_endian_); |
-} |
- |
-// Helper to prepend an ASN.1 integer. |
-void PrivateKeyInfoCodec::PrependInteger(uint8_t* val, |
- int num_bytes, |
- std::list<uint8_t>* data) { |
- PrependIntegerImpl(val, num_bytes, data, big_endian_); |
-} |
- |
-void PrivateKeyInfoCodec::PrependIntegerImpl(uint8_t* val, |
- int num_bytes, |
- std::list<uint8_t>* data, |
- bool big_endian) { |
- // Reverse input if little-endian. |
- std::vector<uint8_t> tmp; |
- if (!big_endian) { |
- tmp.assign(val, val + num_bytes); |
- std::reverse(tmp.begin(), tmp.end()); |
- val = &tmp.front(); |
- } |
- |
- // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes |
- // from the most-significant end of the integer. |
- int start = 0; |
- while (start < (num_bytes - 1) && val[start] == 0x00) { |
- start++; |
- num_bytes--; |
- } |
- PrependBytes(val, start, num_bytes, data); |
- |
- // ASN.1 integers are signed. To encode a positive integer whose sign bit |
- // (the most significant bit) would otherwise be set and make the number |
- // negative, ASN.1 requires a leading null byte to force the integer to be |
- // positive. |
- uint8_t front = data->front(); |
- if ((front & 0x80) != 0) { |
- data->push_front(0x00); |
- num_bytes++; |
- } |
- |
- PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data); |
-} |
- |
-bool PrivateKeyInfoCodec::ReadInteger(uint8_t** pos, |
- uint8_t* end, |
- std::vector<uint8_t>* out) { |
- return ReadIntegerImpl(pos, end, out, big_endian_); |
-} |
- |
-bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize( |
- uint8_t** pos, |
- uint8_t* end, |
- size_t expected_size, |
- std::vector<uint8_t>* out) { |
- std::vector<uint8_t> temp; |
- if (!ReadIntegerImpl(pos, end, &temp, true)) // Big-Endian |
- return false; |
- |
- int pad = expected_size - temp.size(); |
- int index = 0; |
- if (out->size() == expected_size + 1) { |
- READ_ASSERT(out->front() == 0x00); |
- pad++; |
- index++; |
- } else { |
- READ_ASSERT(out->size() <= expected_size); |
- } |
- |
- out->insert(out->end(), pad, 0x00); |
- out->insert(out->end(), temp.begin(), temp.end()); |
- |
- // Reverse output if little-endian. |
- if (!big_endian_) |
- std::reverse(out->begin(), out->end()); |
- return true; |
-} |
- |
-bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8_t** pos, |
- uint8_t* end, |
- std::vector<uint8_t>* out, |
- bool big_endian) { |
- uint32_t length = 0; |
- if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length) |
- return false; |
- |
- // The first byte can be zero to force positiveness. We can ignore this. |
- if (**pos == 0x00) { |
- ++(*pos); |
- --length; |
- } |
- |
- if (length) |
- out->insert(out->end(), *pos, (*pos) + length); |
- |
- (*pos) += length; |
- |
- // Reverse output if little-endian. |
- if (!big_endian) |
- std::reverse(out->begin(), out->end()); |
- return true; |
-} |
- |
-void PrivateKeyInfoCodec::PrependBytes(uint8_t* val, |
- int start, |
- int num_bytes, |
- std::list<uint8_t>* data) { |
- while (num_bytes > 0) { |
- --num_bytes; |
- data->push_front(val[start + num_bytes]); |
- } |
-} |
- |
-void PrivateKeyInfoCodec::PrependLength(size_t size, std::list<uint8_t>* data) { |
- // The high bit is used to indicate whether additional octets are needed to |
- // represent the length. |
- if (size < 0x80) { |
- data->push_front(static_cast<uint8_t>(size)); |
- } else { |
- uint8_t num_bytes = 0; |
- while (size > 0) { |
- data->push_front(static_cast<uint8_t>(size & 0xFF)); |
- size >>= 8; |
- num_bytes++; |
- } |
- CHECK_LE(num_bytes, 4); |
- data->push_front(0x80 | num_bytes); |
- } |
-} |
- |
-void PrivateKeyInfoCodec::PrependTypeHeaderAndLength( |
- uint8_t type, |
- uint32_t length, |
- std::list<uint8_t>* output) { |
- PrependLength(length, output); |
- output->push_front(type); |
-} |
- |
-void PrivateKeyInfoCodec::PrependBitString(uint8_t* val, |
- int num_bytes, |
- std::list<uint8_t>* output) { |
- // Start with the data. |
- PrependBytes(val, 0, num_bytes, output); |
- // Zero unused bits. |
- output->push_front(0); |
- // Add the length. |
- PrependLength(num_bytes + 1, output); |
- // Finally, add the bit string tag. |
- output->push_front((uint8_t)kBitStringTag); |
-} |
- |
-bool PrivateKeyInfoCodec::ReadLength(uint8_t** pos, |
- uint8_t* end, |
- uint32_t* result) { |
- READ_ASSERT(*pos < end); |
- int length = 0; |
- |
- // If the MSB is not set, the length is just the byte itself. |
- if (!(**pos & 0x80)) { |
- length = **pos; |
- (*pos)++; |
- } else { |
- // Otherwise, the lower 7 indicate the length of the length. |
- int length_of_length = **pos & 0x7F; |
- READ_ASSERT(length_of_length <= 4); |
- (*pos)++; |
- READ_ASSERT(*pos + length_of_length < end); |
- |
- length = 0; |
- for (int i = 0; i < length_of_length; ++i) { |
- length <<= 8; |
- length |= **pos; |
- (*pos)++; |
- } |
- } |
- |
- READ_ASSERT(*pos + length <= end); |
- if (result) *result = length; |
- return true; |
-} |
- |
-bool PrivateKeyInfoCodec::ReadTypeHeaderAndLength(uint8_t** pos, |
- uint8_t* end, |
- uint8_t expected_tag, |
- uint32_t* length) { |
- READ_ASSERT(*pos < end); |
- READ_ASSERT(**pos == expected_tag); |
- (*pos)++; |
- |
- return ReadLength(pos, end, length); |
-} |
- |
-bool PrivateKeyInfoCodec::ReadSequence(uint8_t** pos, uint8_t* end) { |
- return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL); |
-} |
- |
-bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8_t** pos, uint8_t* end) { |
- READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end); |
- READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier, |
- sizeof(kRsaAlgorithmIdentifier)) == 0); |
- (*pos) += sizeof(kRsaAlgorithmIdentifier); |
- return true; |
-} |
- |
-bool PrivateKeyInfoCodec::ReadVersion(uint8_t** pos, uint8_t* end) { |
- uint32_t length = 0; |
- if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length)) |
- return false; |
- |
- // The version should be zero. |
- for (uint32_t i = 0; i < length; ++i) { |
- READ_ASSERT(**pos == 0x00); |
- (*pos)++; |
- } |
- |
- return true; |
-} |
- |
-} // namespace |
- |
-namespace crypto { |
- |
-RSAPrivateKey::~RSAPrivateKey() { |
- if (key_) |
- SECKEY_DestroyPrivateKey(key_); |
- if (public_key_) |
- SECKEY_DestroyPublicKey(public_key_); |
-} |
- |
-// static |
-RSAPrivateKey* RSAPrivateKey::Create(uint16_t num_bits) { |
- EnsureNSSInit(); |
- |
- ScopedPK11Slot slot(PK11_GetInternalSlot()); |
- if (!slot) { |
- NOTREACHED(); |
- return nullptr; |
- } |
- |
- ScopedSECKEYPublicKey public_key; |
- ScopedSECKEYPrivateKey private_key; |
- if (!GenerateRSAKeyPairNSS(slot.get(), num_bits, false /* not permanent */, |
- &public_key, &private_key)) { |
- return nullptr; |
- } |
- |
- RSAPrivateKey* rsa_key = new RSAPrivateKey; |
- rsa_key->public_key_ = public_key.release(); |
- rsa_key->key_ = private_key.release(); |
- return rsa_key; |
-} |
- |
-// static |
-RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( |
- const std::vector<uint8_t>& input) { |
- EnsureNSSInit(); |
- |
- ScopedPK11Slot slot(PK11_GetInternalSlot()); |
- if (!slot) { |
- NOTREACHED(); |
- return nullptr; |
- } |
- ScopedSECKEYPrivateKey key(ImportNSSKeyFromPrivateKeyInfo( |
- slot.get(), input, false /* not permanent */)); |
- if (!key || SECKEY_GetPrivateKeyType(key.get()) != rsaKey) |
- return nullptr; |
- return RSAPrivateKey::CreateFromKey(key.get()); |
-} |
- |
-// static |
-RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) { |
- DCHECK(key); |
- if (SECKEY_GetPrivateKeyType(key) != rsaKey) |
- return NULL; |
- RSAPrivateKey* copy = new RSAPrivateKey(); |
- copy->key_ = SECKEY_CopyPrivateKey(key); |
- copy->public_key_ = SECKEY_ConvertToPublicKey(key); |
- if (!copy->key_ || !copy->public_key_) { |
- NOTREACHED(); |
- delete copy; |
- return NULL; |
- } |
- return copy; |
-} |
- |
-RSAPrivateKey* RSAPrivateKey::Copy() const { |
- RSAPrivateKey* copy = new RSAPrivateKey(); |
- copy->key_ = SECKEY_CopyPrivateKey(key_); |
- copy->public_key_ = SECKEY_CopyPublicKey(public_key_); |
- return copy; |
-} |
- |
-bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const { |
- PrivateKeyInfoCodec private_key_info(true); |
- |
- // Manually read the component attributes of the private key and build up |
- // the PrivateKeyInfo. |
- if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) || |
- !ReadAttribute(key_, CKA_PUBLIC_EXPONENT, |
- private_key_info.public_exponent()) || |
- !ReadAttribute(key_, CKA_PRIVATE_EXPONENT, |
- private_key_info.private_exponent()) || |
- !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) || |
- !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) || |
- !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) || |
- !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) || |
- !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) { |
- NOTREACHED(); |
- return false; |
- } |
- |
- return private_key_info.Export(output); |
-} |
- |
-bool RSAPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const { |
- ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_)); |
- if (!der_pubkey.get()) { |
- NOTREACHED(); |
- return false; |
- } |
- |
- output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len); |
- return true; |
-} |
- |
-RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) { |
- EnsureNSSInit(); |
-} |
- |
-} // namespace crypto |