1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "crypto/rsa_private_key.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/string_util.h"
14 // This file manually encodes and decodes RSA private keys using PrivateKeyInfo
15 // from PKCS #8 and RSAPrivateKey from PKCS #1. These structures are:
17 // PrivateKeyInfo ::= SEQUENCE {
19 // privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
20 // privateKey PrivateKey,
21 // attributes [0] IMPLICIT Attributes OPTIONAL
24 // RSAPrivateKey ::= SEQUENCE {
27 // publicExponent INTEGER,
28 // privateExponent INTEGER,
33 // coefficient INTEGER
37 // Helper for error handling during key import.
38 #define READ_ASSERT(truth) \
47 const uint8
PrivateKeyInfoCodec::kRsaAlgorithmIdentifier
[] = {
48 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
52 PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian
)
53 : big_endian_(big_endian
) {}
55 PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {}
57 bool PrivateKeyInfoCodec::Export(std::vector
<uint8
>* output
) {
58 std::list
<uint8
> content
;
60 // Version (always zero)
63 PrependInteger(coefficient_
, &content
);
64 PrependInteger(exponent2_
, &content
);
65 PrependInteger(exponent1_
, &content
);
66 PrependInteger(prime2_
, &content
);
67 PrependInteger(prime1_
, &content
);
68 PrependInteger(private_exponent_
, &content
);
69 PrependInteger(public_exponent_
, &content
);
70 PrependInteger(modulus_
, &content
);
71 PrependInteger(&version
, 1, &content
);
72 PrependTypeHeaderAndLength(kSequenceTag
, content
.size(), &content
);
73 PrependTypeHeaderAndLength(kOctetStringTag
, content
.size(), &content
);
76 for (size_t i
= sizeof(kRsaAlgorithmIdentifier
); i
> 0; --i
)
77 content
.push_front(kRsaAlgorithmIdentifier
[i
- 1]);
79 PrependInteger(&version
, 1, &content
);
80 PrependTypeHeaderAndLength(kSequenceTag
, content
.size(), &content
);
82 // Copy everying into the output.
83 output
->reserve(content
.size());
84 for (std::list
<uint8
>::iterator i
= content
.begin(); i
!= content
.end(); ++i
)
85 output
->push_back(*i
);
90 bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector
<uint8
>* output
) {
91 // Create a sequence with the modulus (n) and public exponent (e).
92 std::vector
<uint8
> bit_string
;
93 if (!ExportPublicKey(&bit_string
))
96 // Add the sequence as the contents of a bit string.
97 std::list
<uint8
> content
;
98 PrependBitString(&bit_string
[0], static_cast<int>(bit_string
.size()),
101 // Add the RSA algorithm OID.
102 for (size_t i
= sizeof(kRsaAlgorithmIdentifier
); i
> 0; --i
)
103 content
.push_front(kRsaAlgorithmIdentifier
[i
- 1]);
105 // Finally, wrap everything in a sequence.
106 PrependTypeHeaderAndLength(kSequenceTag
, content
.size(), &content
);
108 // Copy everything into the output.
109 output
->reserve(content
.size());
110 for (std::list
<uint8
>::iterator i
= content
.begin(); i
!= content
.end(); ++i
)
111 output
->push_back(*i
);
116 bool PrivateKeyInfoCodec::ExportPublicKey(std::vector
<uint8
>* output
) {
117 // Create a sequence with the modulus (n) and public exponent (e).
118 std::list
<uint8
> content
;
119 PrependInteger(&public_exponent_
[0],
120 static_cast<int>(public_exponent_
.size()),
122 PrependInteger(&modulus_
[0], static_cast<int>(modulus_
.size()), &content
);
123 PrependTypeHeaderAndLength(kSequenceTag
, content
.size(), &content
);
125 // Copy everything into the output.
126 output
->reserve(content
.size());
127 for (std::list
<uint8
>::iterator i
= content
.begin(); i
!= content
.end(); ++i
)
128 output
->push_back(*i
);
133 bool PrivateKeyInfoCodec::Import(const std::vector
<uint8
>& input
) {
138 // Parse the private key info up to the public key values, ignoring
139 // the subsequent private key values.
140 uint8
* src
= const_cast<uint8
*>(&input
.front());
141 uint8
* end
= src
+ input
.size();
142 if (!ReadSequence(&src
, end
) ||
143 !ReadVersion(&src
, end
) ||
144 !ReadAlgorithmIdentifier(&src
, end
) ||
145 !ReadTypeHeaderAndLength(&src
, end
, kOctetStringTag
, NULL
) ||
146 !ReadSequence(&src
, end
) ||
147 !ReadVersion(&src
, end
) ||
148 !ReadInteger(&src
, end
, &modulus_
))
151 int mod_size
= modulus_
.size();
152 READ_ASSERT(mod_size
% 2 == 0);
153 int primes_size
= mod_size
/ 2;
155 if (!ReadIntegerWithExpectedSize(&src
, end
, 4, &public_exponent_
) ||
156 !ReadIntegerWithExpectedSize(&src
, end
, mod_size
, &private_exponent_
) ||
157 !ReadIntegerWithExpectedSize(&src
, end
, primes_size
, &prime1_
) ||
158 !ReadIntegerWithExpectedSize(&src
, end
, primes_size
, &prime2_
) ||
159 !ReadIntegerWithExpectedSize(&src
, end
, primes_size
, &exponent1_
) ||
160 !ReadIntegerWithExpectedSize(&src
, end
, primes_size
, &exponent2_
) ||
161 !ReadIntegerWithExpectedSize(&src
, end
, primes_size
, &coefficient_
))
164 READ_ASSERT(src
== end
);
170 void PrivateKeyInfoCodec::PrependInteger(const std::vector
<uint8
>& in
,
171 std::list
<uint8
>* out
) {
172 uint8
* ptr
= const_cast<uint8
*>(&in
.front());
173 PrependIntegerImpl(ptr
, in
.size(), out
, big_endian_
);
176 // Helper to prepend an ASN.1 integer.
177 void PrivateKeyInfoCodec::PrependInteger(uint8
* val
,
179 std::list
<uint8
>* data
) {
180 PrependIntegerImpl(val
, num_bytes
, data
, big_endian_
);
183 void PrivateKeyInfoCodec::PrependIntegerImpl(uint8
* val
,
185 std::list
<uint8
>* data
,
187 // Reverse input if little-endian.
188 std::vector
<uint8
> tmp
;
190 tmp
.assign(val
, val
+ num_bytes
);
191 reverse(tmp
.begin(), tmp
.end());
195 // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes
196 // from the most-significant end of the integer.
198 while (start
< (num_bytes
- 1) && val
[start
] == 0x00) {
202 PrependBytes(val
, start
, num_bytes
, data
);
204 // ASN.1 integers are signed. To encode a positive integer whose sign bit
205 // (the most significant bit) would otherwise be set and make the number
206 // negative, ASN.1 requires a leading null byte to force the integer to be
208 uint8 front
= data
->front();
209 if ((front
& 0x80) != 0) {
210 data
->push_front(0x00);
214 PrependTypeHeaderAndLength(kIntegerTag
, num_bytes
, data
);
217 bool PrivateKeyInfoCodec::ReadInteger(uint8
** pos
,
219 std::vector
<uint8
>* out
) {
220 return ReadIntegerImpl(pos
, end
, out
, big_endian_
);
223 bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8
** pos
,
225 size_t expected_size
,
226 std::vector
<uint8
>* out
) {
227 std::vector
<uint8
> temp
;
228 if (!ReadIntegerImpl(pos
, end
, &temp
, true)) // Big-Endian
231 int pad
= expected_size
- temp
.size();
233 if (out
->size() == expected_size
+ 1) {
234 READ_ASSERT(out
->front() == 0x00);
238 READ_ASSERT(out
->size() <= expected_size
);
242 out
->push_back(0x00);
245 out
->insert(out
->end(), temp
.begin(), temp
.end());
247 // Reverse output if little-endian.
249 reverse(out
->begin(), out
->end());
253 bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8
** pos
,
255 std::vector
<uint8
>* out
,
258 if (!ReadTypeHeaderAndLength(pos
, end
, kIntegerTag
, &length
) || !length
)
261 // The first byte can be zero to force positiveness. We can ignore this.
268 out
->insert(out
->end(), *pos
, (*pos
) + length
);
272 // Reverse output if little-endian.
274 reverse(out
->begin(), out
->end());
278 void PrivateKeyInfoCodec::PrependBytes(uint8
* val
,
281 std::list
<uint8
>* data
) {
282 while (num_bytes
> 0) {
284 data
->push_front(val
[start
+ num_bytes
]);
288 void PrivateKeyInfoCodec::PrependLength(size_t size
, std::list
<uint8
>* data
) {
289 // The high bit is used to indicate whether additional octets are needed to
290 // represent the length.
292 data
->push_front(static_cast<uint8
>(size
));
296 data
->push_front(static_cast<uint8
>(size
& 0xFF));
300 CHECK_LE(num_bytes
, 4);
301 data
->push_front(0x80 | num_bytes
);
305 void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(uint8 type
,
307 std::list
<uint8
>* output
) {
308 PrependLength(length
, output
);
309 output
->push_front(type
);
312 void PrivateKeyInfoCodec::PrependBitString(uint8
* val
,
314 std::list
<uint8
>* output
) {
315 // Start with the data.
316 PrependBytes(val
, 0, num_bytes
, output
);
318 output
->push_front(0);
320 PrependLength(num_bytes
+ 1, output
);
321 // Finally, add the bit string tag.
322 output
->push_front((uint8
) kBitStringTag
);
325 bool PrivateKeyInfoCodec::ReadLength(uint8
** pos
, uint8
* end
, uint32
* result
) {
326 READ_ASSERT(*pos
< end
);
329 // If the MSB is not set, the length is just the byte itself.
330 if (!(**pos
& 0x80)) {
334 // Otherwise, the lower 7 indicate the length of the length.
335 int length_of_length
= **pos
& 0x7F;
336 READ_ASSERT(length_of_length
<= 4);
338 READ_ASSERT(*pos
+ length_of_length
< end
);
341 for (int i
= 0; i
< length_of_length
; ++i
) {
348 READ_ASSERT(*pos
+ length
<= end
);
349 if (result
) *result
= length
;
353 bool PrivateKeyInfoCodec::ReadTypeHeaderAndLength(uint8
** pos
,
357 READ_ASSERT(*pos
< end
);
358 READ_ASSERT(**pos
== expected_tag
);
361 return ReadLength(pos
, end
, length
);
364 bool PrivateKeyInfoCodec::ReadSequence(uint8
** pos
, uint8
* end
) {
365 return ReadTypeHeaderAndLength(pos
, end
, kSequenceTag
, NULL
);
368 bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8
** pos
, uint8
* end
) {
369 READ_ASSERT(*pos
+ sizeof(kRsaAlgorithmIdentifier
) < end
);
370 READ_ASSERT(memcmp(*pos
, kRsaAlgorithmIdentifier
,
371 sizeof(kRsaAlgorithmIdentifier
)) == 0);
372 (*pos
) += sizeof(kRsaAlgorithmIdentifier
);
376 bool PrivateKeyInfoCodec::ReadVersion(uint8
** pos
, uint8
* end
) {
378 if (!ReadTypeHeaderAndLength(pos
, end
, kIntegerTag
, &length
))
381 // The version should be zero.
382 for (uint32 i
= 0; i
< length
; ++i
) {
383 READ_ASSERT(**pos
== 0x00);
390 } // namespace crypto