OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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. | |
4 | |
5 #include "components/proximity_auth/cryptauth/fake_secure_message_delegate.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/callback.h" | |
10 #include "base/md5.h" | |
11 | |
12 namespace proximity_auth { | |
13 | |
14 namespace { | |
15 | |
16 const char kKeyPrefix[] = "fake_key_"; | |
17 const char kPrivateKeyPrefix[] = "private_"; | |
18 | |
19 // Encrypts the |plaintext| with the |key| using the |encryption_scheme| and | |
20 // returns the ciphertext. | |
21 std::string Encrypt(const std::string& plaintext, | |
22 const std::string& key, | |
23 const securemessage::EncScheme& encryption_scheme) { | |
24 if (encryption_scheme == securemessage::NONE) | |
25 return plaintext; | |
26 | |
27 // Encrypt with a Vigenere cipher. | |
28 std::string ciphertext; | |
29 ciphertext.resize(plaintext.size()); | |
30 for (size_t i = 0; i < plaintext.size(); ++i) { | |
31 unsigned char plaintext_char = plaintext[i]; | |
32 unsigned char key_char = key[i % key.size()]; | |
33 ciphertext[i] = plaintext_char + key_char; | |
34 } | |
35 return ciphertext; | |
36 } | |
37 | |
38 // Decrypts the |ciphertext| with the |key| using the |encryption_scheme| and | |
39 // returns the plaintext. | |
40 std::string Decrypt(const std::string& ciphertext, | |
41 const std::string& key, | |
42 const securemessage::EncScheme& encryption_scheme) { | |
43 if (encryption_scheme == securemessage::NONE) | |
44 return ciphertext; | |
45 | |
46 // Decrypt with a Vigenere cipher. | |
47 std::string plaintext; | |
48 plaintext.resize(ciphertext.size()); | |
49 for (size_t i = 0; i < ciphertext.size(); ++i) { | |
50 unsigned char ciphertext_char = ciphertext[i]; | |
51 unsigned char key_char = key[i % key.size()]; | |
52 plaintext[i] = ciphertext_char - key_char; | |
53 } | |
54 return plaintext; | |
55 } | |
56 | |
57 // Signs the |payload| and |associated_data| with the |key| using the | |
58 // |signature_scheme| and returns the signature. | |
59 std::string Sign(const std::string& payload, | |
60 const std::string& associated_data, | |
61 const std::string& key, | |
62 const securemessage::SigScheme& signature_scheme) { | |
Ilya Sherman
2015/04/03 22:43:41
nit: The |signature_scheme| is not used, so let's
Tim Song
2015/04/04 05:06:14
Done.
| |
63 return base::MD5String(payload + "|" + associated_data + "|" + key); | |
64 } | |
65 | |
66 // Verifies that the |signature| for the the |payload| and |associated_data| is | |
67 // valid for the given the |key| and |signature_scheme|. | |
68 bool Verify(const std::string& signature, | |
69 const std::string& payload, | |
70 const std::string& associated_data, | |
71 const std::string& key, | |
72 const securemessage::SigScheme& signature_scheme) { | |
73 // Verify signatures created using symmetric keys. | |
74 if (signature_scheme == securemessage::HMAC_SHA256) { | |
75 std::string expected_signature = | |
76 Sign(payload, associated_data, key, signature_scheme); | |
77 return signature == expected_signature; | |
78 } | |
Ilya Sherman
2015/04/03 22:43:41
I think this method would be clearer if it were st
Tim Song
2015/04/04 05:06:14
Done.
| |
79 | |
80 // Verify signatures created using asymmetric keys. | |
81 std::string prefix = kPrivateKeyPrefix; | |
82 bool is_private_key = key.substr(0, prefix.size()) == prefix; | |
83 std::string signing_key = | |
84 is_private_key ? key.substr(prefix.size()) : prefix + key; | |
85 | |
86 std::string expected_signature = | |
87 Sign(payload, associated_data, signing_key, signature_scheme); | |
88 << signature_scheme; | |
Ilya Sherman
2015/04/03 22:43:41
Hmm?
Tim Song
2015/04/04 05:06:14
Sorry, forgot to delete this.
| |
89 return signature == expected_signature; | |
90 } | |
91 } | |
92 | |
93 FakeSecureMessageDelegate::FakeSecureMessageDelegate() | |
94 : next_public_key_(std::string(kKeyPrefix) + "0") { | |
95 } | |
96 | |
97 FakeSecureMessageDelegate::~FakeSecureMessageDelegate() { | |
98 } | |
99 | |
100 void FakeSecureMessageDelegate::GenerateKeyPair( | |
101 const GenerateKeyPairCallback& callback) { | |
102 std::string public_key = next_public_key_; | |
103 | |
104 // The private key is simply the public key prepended with "private_". | |
105 std::string private_key(std::string(kPrivateKeyPrefix + public_key)); | |
Ilya Sherman
2015/04/03 22:43:41
nit: No need for the inner "std::string"
Tim Song
2015/04/04 05:06:14
Done.
| |
106 | |
107 next_public_key_ = std::string(kKeyPrefix) + base::MD5String(public_key); | |
108 | |
109 callback.Run(public_key, private_key); | |
110 } | |
111 | |
112 void FakeSecureMessageDelegate::DeriveKey(const std::string& private_key, | |
113 const std::string& public_key, | |
114 const DeriveKeyCallback& callback) { | |
115 // Ensure that the same symmetric is derived for DeriveKey(private1, public2) | |
Ilya Sherman
2015/04/03 22:43:41
nit: "same symmetric" -> "same symmetric key"
Tim Song
2015/04/04 05:06:14
Done.
| |
116 // and DeriveKey(private2, public1). | |
Ilya Sherman
2015/04/03 22:43:41
I think it would help to explain, in the comment,
Tim Song
2015/04/04 05:06:14
Done.
| |
117 std::string prefix(kPrivateKeyPrefix); | |
118 std::string normalized_private_key = | |
119 private_key.size() > prefix.size() | |
Ilya Sherman
2015/04/03 22:43:41
I'm not really following why you're just comparing
Tim Song
2015/04/04 05:06:14
I don't want to call substr with an out of bounds
Ilya Sherman
2015/04/06 18:33:51
I mean, sure, but trimming off the prefix only mak
Tim Song
2015/04/06 19:37:23
All private keys are expected to start with "priva
| |
120 ? private_key.substr(std::string(kPrivateKeyPrefix).size()) | |
Ilya Sherman
2015/04/03 22:43:41
nit: s/std::string(kPrivateKeyPrefix)/prefix
Tim Song
2015/04/04 05:06:14
Done.
| |
121 : private_key; | |
122 | |
123 std::vector<std::string> keys; | |
124 keys.push_back(normalized_private_key); | |
125 keys.push_back(public_key); | |
126 std::sort(keys.begin(), keys.end()); | |
127 callback.Run(base::MD5String(keys[0] + "|" + keys[1])); | |
128 } | |
129 | |
130 void FakeSecureMessageDelegate::CreateSecureMessage( | |
131 const std::string& payload, | |
132 const std::string& key, | |
133 const CreateOptions& create_options, | |
134 const CreateSecureMessageCallback& callback) { | |
135 securemessage::Header header; | |
136 header.set_signature_scheme(create_options.signature_scheme); | |
137 header.set_encryption_scheme(create_options.encryption_scheme); | |
138 if (!create_options.public_metadata.empty()) | |
139 header.set_public_metadata(create_options.public_metadata); | |
140 if (!create_options.verification_key_id.empty()) | |
141 header.set_verification_key_id(create_options.verification_key_id); | |
142 if (!create_options.decryption_key_id.empty()) | |
143 header.set_decryption_key_id(create_options.decryption_key_id); | |
144 | |
145 securemessage::HeaderAndBody header_and_body; | |
146 header_and_body.mutable_header()->CopyFrom(header); | |
147 header_and_body.set_body( | |
148 Encrypt(payload, key, create_options.encryption_scheme)); | |
149 std::string serialized_header_and_body; | |
150 header_and_body.SerializeToString(&serialized_header_and_body); | |
151 | |
152 securemessage::SecureMessage secure_message; | |
153 secure_message.set_header_and_body(serialized_header_and_body); | |
154 secure_message.set_signature(Sign(payload, create_options.associated_data, | |
155 key, create_options.signature_scheme)); | |
156 | |
157 std::string serialized_secure_message; | |
158 secure_message.SerializeToString(&serialized_secure_message); | |
159 callback.Run(serialized_secure_message); | |
160 } | |
Ilya Sherman
2015/04/03 22:43:41
Most of this seems appropriate to do in the base c
Tim Song
2015/04/04 05:06:14
We need to keep SecureMessageDelegate as an interf
| |
161 | |
162 void FakeSecureMessageDelegate::UnwrapSecureMessage( | |
163 const std::string& serialized_message, | |
164 const std::string& key, | |
165 const UnwrapOptions& unwrap_options, | |
166 const UnwrapSecureMessageCallback& callback) { | |
167 securemessage::SecureMessage secure_message; | |
168 if (!secure_message.ParseFromString(serialized_message)) { | |
169 LOG(ERROR) << "Failed to parse SecureMessage."; | |
170 callback.Run(false, std::string(), securemessage::Header()); | |
171 return; | |
172 } | |
173 | |
174 securemessage::HeaderAndBody header_and_body; | |
175 if (!header_and_body.ParseFromString(secure_message.header_and_body())) { | |
176 LOG(ERROR) << "Failed to parse secure message HeaderAndBody."; | |
177 callback.Run(false, std::string(), securemessage::Header()); | |
178 return; | |
179 } | |
180 | |
181 const securemessage::Header& header = header_and_body.header(); | |
182 std::string payload = | |
183 Decrypt(header_and_body.body(), key, unwrap_options.encryption_scheme); | |
184 | |
185 bool verified = Verify(secure_message.signature(), payload, | |
186 unwrap_options.associated_data, key, | |
187 unwrap_options.signature_scheme); | |
188 if (verified) { | |
189 callback.Run(true, payload, header); | |
190 } else { | |
191 callback.Run(false, std::string(), securemessage::Header()); | |
192 } | |
193 } | |
Ilya Sherman
2015/04/03 22:43:41
Same applies here.
Tim Song
2015/04/04 05:06:14
Same reasoning.
| |
194 | |
195 } // namespace proximity_auth | |
OLD | NEW |