Shaka Packager SDK
rsa_key.cc
1 // Copyright 2014 Google Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 //
7 // RSA signature details:
8 // Algorithm: RSASSA-PSS
9 // Hash algorithm: SHA1
10 // Mask generation function: mgf1SHA1
11 // Salt length: 20 bytes
12 // Trailer field: 0xbc
13 //
14 // RSA encryption details:
15 // Algorithm: RSA-OAEP
16 // Mask generation function: mgf1SHA1
17 // Label (encoding paramter): empty std::string
18 
19 #include "packager/media/base/rsa_key.h"
20 
21 #include <openssl/err.h>
22 #include <openssl/rsa.h>
23 #include <openssl/x509.h>
24 #include <vector>
25 
26 #include "packager/base/logging.h"
27 #include "packager/base/sha1.h"
28 
29 namespace {
30 
31 const size_t kPssSaltLength = 20u;
32 
33 // Serialize rsa key from DER encoded PKCS#1 RSAPrivateKey.
34 RSA* DeserializeRsaKey(const std::string& serialized_key,
35  bool deserialize_private_key) {
36  if (serialized_key.empty()) {
37  LOG(ERROR) << "Serialized RSA Key is empty.";
38  return NULL;
39  }
40 
41  BIO* bio = BIO_new_mem_buf(const_cast<char*>(serialized_key.data()),
42  serialized_key.size());
43  if (bio == NULL) {
44  LOG(ERROR) << "BIO_new_mem_buf returned NULL.";
45  return NULL;
46  }
47  RSA* rsa_key = deserialize_private_key ? d2i_RSAPrivateKey_bio(bio, NULL)
48  : d2i_RSAPublicKey_bio(bio, NULL);
49  BIO_free(bio);
50  return rsa_key;
51 }
52 
53 RSA* DeserializeRsaPrivateKey(const std::string& serialized_key) {
54  RSA* rsa_key = DeserializeRsaKey(serialized_key, true);
55  if (!rsa_key) {
56  LOG(ERROR) << "Private RSA key deserialization failure.";
57  return NULL;
58  }
59  if (RSA_check_key(rsa_key) != 1) {
60  LOG(ERROR) << "Invalid RSA Private key: " << ERR_error_string(
61  ERR_get_error(), NULL);
62  RSA_free(rsa_key);
63  return NULL;
64  }
65  return rsa_key;
66 }
67 
68 RSA* DeserializeRsaPublicKey(const std::string& serialized_key) {
69  RSA* rsa_key = DeserializeRsaKey(serialized_key, false);
70  if (!rsa_key) {
71  LOG(ERROR) << "Private RSA key deserialization failure.";
72  return NULL;
73  }
74  if (RSA_size(rsa_key) <= 0) {
75  LOG(ERROR) << "Invalid RSA Public key: " << ERR_error_string(
76  ERR_get_error(), NULL);
77  RSA_free(rsa_key);
78  return NULL;
79  }
80  return rsa_key;
81 }
82 
83 } // namespace
84 
85 namespace shaka {
86 namespace media {
87 
88 RsaPrivateKey::RsaPrivateKey(RSA* rsa_key) : rsa_key_(rsa_key) {
89  DCHECK(rsa_key);
90 }
91 RsaPrivateKey::~RsaPrivateKey() {
92  if (rsa_key_ != NULL)
93  RSA_free(rsa_key_);
94 }
95 
96 RsaPrivateKey* RsaPrivateKey::Create(const std::string& serialized_key) {
97  RSA* rsa_key = DeserializeRsaPrivateKey(serialized_key);
98  return rsa_key == NULL ? NULL : new RsaPrivateKey(rsa_key);
99 }
100 
101 bool RsaPrivateKey::Decrypt(const std::string& encrypted_message,
102  std::string* decrypted_message) {
103  DCHECK(decrypted_message);
104 
105  size_t rsa_size = RSA_size(rsa_key_);
106  if (encrypted_message.size() != rsa_size) {
107  LOG(ERROR) << "Encrypted RSA message has the wrong size (expected "
108  << rsa_size << ", actual " << encrypted_message.size() << ").";
109  return false;
110  }
111 
112  decrypted_message->resize(rsa_size);
113  int decrypted_size = RSA_private_decrypt(
114  rsa_size, reinterpret_cast<const uint8_t*>(encrypted_message.data()),
115  reinterpret_cast<uint8_t*>(&(*decrypted_message)[0]), rsa_key_,
116  RSA_PKCS1_OAEP_PADDING);
117 
118  if (decrypted_size == -1) {
119  LOG(ERROR) << "RSA private decrypt failure: " << ERR_error_string(
120  ERR_get_error(), NULL);
121  return false;
122  }
123  decrypted_message->resize(decrypted_size);
124  return true;
125 }
126 
127 bool RsaPrivateKey::GenerateSignature(const std::string& message,
128  std::string* signature) {
129  DCHECK(signature);
130  if (message.empty()) {
131  LOG(ERROR) << "Message to be signed is empty.";
132  return false;
133  }
134 
135  std::string message_digest = base::SHA1HashString(message);
136 
137  // Add PSS padding.
138  size_t rsa_size = RSA_size(rsa_key_);
139  std::vector<uint8_t> padded_digest(rsa_size);
140  if (!RSA_padding_add_PKCS1_PSS_mgf1(
141  rsa_key_, &padded_digest[0],
142  reinterpret_cast<uint8_t*>(&message_digest[0]), EVP_sha1(),
143  EVP_sha1(), kPssSaltLength)) {
144  LOG(ERROR) << "RSA padding failure: " << ERR_error_string(ERR_get_error(),
145  NULL);
146  return false;
147  }
148 
149  // Encrypt PSS padded digest.
150  signature->resize(rsa_size);
151  int signature_size = RSA_private_encrypt(
152  padded_digest.size(), &padded_digest[0],
153  reinterpret_cast<uint8_t*>(&(*signature)[0]), rsa_key_, RSA_NO_PADDING);
154 
155  if (signature_size != static_cast<int>(rsa_size)) {
156  LOG(ERROR) << "RSA private encrypt failure: " << ERR_error_string(
157  ERR_get_error(), NULL);
158  return false;
159  }
160  return true;
161 }
162 
163 RsaPublicKey::RsaPublicKey(RSA* rsa_key) : rsa_key_(rsa_key) {
164  DCHECK(rsa_key);
165 }
166 RsaPublicKey::~RsaPublicKey() {
167  if (rsa_key_ != NULL)
168  RSA_free(rsa_key_);
169 }
170 
171 RsaPublicKey* RsaPublicKey::Create(const std::string& serialized_key) {
172  RSA* rsa_key = DeserializeRsaPublicKey(serialized_key);
173  return rsa_key == NULL ? NULL : new RsaPublicKey(rsa_key);
174 }
175 
176 bool RsaPublicKey::Encrypt(const std::string& clear_message,
177  std::string* encrypted_message) {
178  DCHECK(encrypted_message);
179  if (clear_message.empty()) {
180  LOG(ERROR) << "Message to be encrypted is empty.";
181  return false;
182  }
183 
184  size_t rsa_size = RSA_size(rsa_key_);
185  encrypted_message->resize(rsa_size);
186  int encrypted_size =
187  RSA_public_encrypt(clear_message.size(),
188  reinterpret_cast<const uint8_t*>(clear_message.data()),
189  reinterpret_cast<uint8_t*>(&(*encrypted_message)[0]),
190  rsa_key_, RSA_PKCS1_OAEP_PADDING);
191 
192  if (encrypted_size != static_cast<int>(rsa_size)) {
193  LOG(ERROR) << "RSA public encrypt failure: " << ERR_error_string(
194  ERR_get_error(), NULL);
195  return false;
196  }
197  return true;
198 }
199 
200 bool RsaPublicKey::VerifySignature(const std::string& message,
201  const std::string& signature) {
202  if (message.empty()) {
203  LOG(ERROR) << "Signed message is empty.";
204  return false;
205  }
206 
207  size_t rsa_size = RSA_size(rsa_key_);
208  if (signature.size() != rsa_size) {
209  LOG(ERROR) << "Message signature is of the wrong size (expected "
210  << rsa_size << ", actual " << signature.size() << ").";
211  return false;
212  }
213 
214  // Decrypt the signature.
215  std::vector<uint8_t> padded_digest(signature.size());
216  int decrypted_size =
217  RSA_public_decrypt(signature.size(),
218  reinterpret_cast<const uint8_t*>(signature.data()),
219  &padded_digest[0],
220  rsa_key_,
221  RSA_NO_PADDING);
222 
223  if (decrypted_size != static_cast<int>(rsa_size)) {
224  LOG(ERROR) << "RSA public decrypt failure: " << ERR_error_string(
225  ERR_get_error(), NULL);
226  return false;
227  }
228 
229  std::string message_digest = base::SHA1HashString(message);
230 
231  // Verify PSS padding.
232  return RSA_verify_PKCS1_PSS_mgf1(
233  rsa_key_,
234  reinterpret_cast<const uint8_t*>(message_digest.data()),
235  EVP_sha1(),
236  EVP_sha1(),
237  &padded_digest[0],
238  kPssSaltLength) != 0;
239 }
240 
241 } // namespace media
242 } // namespace shaka
shaka::media::RsaPrivateKey
Rsa private key, used for message signing and decryption.
Definition: rsa_key.h:24
shaka
All the methods that are virtual are virtual for mocking.
Definition: gflags_hex_bytes.cc:11
shaka::media::RsaPrivateKey::Create
static RsaPrivateKey * Create(const std::string &serialized_key)
Definition: rsa_key.cc:96
shaka::media::RsaPublicKey
Rsa public key, used for signature verification and encryption.
Definition: rsa_key.h:53
shaka::media::RsaPublicKey::VerifySignature
bool VerifySignature(const std::string &message, const std::string &signature)
Definition: rsa_key.cc:200
shaka::media::RsaPrivateKey::GenerateSignature
bool GenerateSignature(const std::string &message, std::string *signature)
Definition: rsa_key.cc:127
shaka::media::RsaPublicKey::Encrypt
bool Encrypt(const std::string &clear_message, std::string *encrypted_message)
Definition: rsa_key.cc:176
shaka::media::RsaPublicKey::Create
static RsaPublicKey * Create(const std::string &serialized_key)
Definition: rsa_key.cc:171
shaka::media::RsaPrivateKey::Decrypt
bool Decrypt(const std::string &encrypted_message, std::string *decrypted_message)
Definition: rsa_key.cc:101