Update mojo sdk to rev c02a28868825edfa57ab77947b8cb15e741c5598
[chromium-blink-merge.git] / components / proximity_auth / cryptauth / fake_secure_message_delegate.cc
blob4251e1991b06d9b2e255125c5adf8eae6e701e0e
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.
5 #include "components/proximity_auth/cryptauth/fake_secure_message_delegate.h"
7 #include <algorithm>
9 #include "base/callback.h"
10 #include "base/md5.h"
11 #include "base/strings/string_util.h"
13 namespace proximity_auth {
15 namespace {
17 const char kKeyPrefix[] = "fake_key_";
18 const char kPrivateKeyPrefix[] = "private_";
20 // Encrypts the |plaintext| with the |key| using the |encryption_scheme| and
21 // returns the ciphertext.
22 std::string Encrypt(const std::string& plaintext,
23 const std::string& key,
24 const securemessage::EncScheme& encryption_scheme) {
25 if (encryption_scheme == securemessage::NONE)
26 return plaintext;
28 // Encrypt with a Vigenere cipher.
29 std::string ciphertext;
30 ciphertext.resize(plaintext.size());
31 for (size_t i = 0; i < plaintext.size(); ++i) {
32 unsigned char plaintext_char = plaintext[i];
33 unsigned char key_char = key[i % key.size()];
34 ciphertext[i] = plaintext_char + key_char;
36 return ciphertext;
39 // Decrypts the |ciphertext| with the |key| using the |encryption_scheme| and
40 // returns the plaintext.
41 std::string Decrypt(const std::string& ciphertext,
42 const std::string& key,
43 const securemessage::EncScheme& encryption_scheme) {
44 if (encryption_scheme == securemessage::NONE)
45 return ciphertext;
47 // Decrypt with a Vigenere cipher.
48 std::string plaintext;
49 plaintext.resize(ciphertext.size());
50 for (size_t i = 0; i < ciphertext.size(); ++i) {
51 unsigned char ciphertext_char = ciphertext[i];
52 unsigned char key_char = key[i % key.size()];
53 plaintext[i] = ciphertext_char - key_char;
55 return plaintext;
58 // Signs the |payload| and |associated_data| with the |key| using the
59 // |signature_scheme| and returns the signature.
60 std::string Sign(const std::string& payload,
61 const std::string& associated_data,
62 const std::string& key) {
63 return base::MD5String(payload + "|" + associated_data + "|" + key);
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 std::string signing_key;
75 if (signature_scheme == securemessage::HMAC_SHA256) {
76 signing_key = key;
77 } else {
78 std::string prefix = kPrivateKeyPrefix;
79 bool is_private_key =
80 base::StartsWith(key, prefix, base::CompareCase::SENSITIVE);
81 signing_key = is_private_key ? key.substr(prefix.size()) : prefix + key;
84 std::string expected_signature = Sign(payload, associated_data, signing_key);
85 return signature == expected_signature;
88 } // namespace
90 FakeSecureMessageDelegate::FakeSecureMessageDelegate()
91 : next_public_key_(std::string(kKeyPrefix) + "0") {
94 FakeSecureMessageDelegate::~FakeSecureMessageDelegate() {
97 void FakeSecureMessageDelegate::GenerateKeyPair(
98 const GenerateKeyPairCallback& callback) {
99 std::string public_key = next_public_key_;
101 // The private key is simply the public key prepended with "private_".
102 std::string private_key(kPrivateKeyPrefix + public_key);
104 next_public_key_ = std::string(kKeyPrefix) + base::MD5String(public_key);
106 callback.Run(public_key, private_key);
109 void FakeSecureMessageDelegate::DeriveKey(const std::string& private_key,
110 const std::string& public_key,
111 const DeriveKeyCallback& callback) {
112 // To ensure that the same symmetric key is derived for DeriveKey(private1,
113 // public2) and DeriveKey(private2, public1), we remove the prefix from the
114 // private key so it is equal to its corresponding public key.
115 std::string prefix(kPrivateKeyPrefix);
116 std::string normalized_private_key =
117 base::StartsWith(private_key, prefix, base::CompareCase::SENSITIVE)
118 ? private_key.substr(prefix.size())
119 : private_key;
121 std::vector<std::string> keys;
122 keys.push_back(normalized_private_key);
123 keys.push_back(public_key);
124 std::sort(keys.begin(), keys.end());
125 callback.Run(base::MD5String(keys[0] + "|" + keys[1]));
128 void FakeSecureMessageDelegate::CreateSecureMessage(
129 const std::string& payload,
130 const std::string& key,
131 const CreateOptions& create_options,
132 const CreateSecureMessageCallback& callback) {
133 securemessage::Header header;
134 header.set_signature_scheme(create_options.signature_scheme);
135 header.set_encryption_scheme(create_options.encryption_scheme);
136 if (!create_options.public_metadata.empty())
137 header.set_public_metadata(create_options.public_metadata);
138 if (!create_options.verification_key_id.empty())
139 header.set_verification_key_id(create_options.verification_key_id);
140 if (!create_options.decryption_key_id.empty())
141 header.set_decryption_key_id(create_options.decryption_key_id);
143 securemessage::HeaderAndBody header_and_body;
144 header_and_body.mutable_header()->CopyFrom(header);
145 header_and_body.set_body(
146 Encrypt(payload, key, create_options.encryption_scheme));
147 std::string serialized_header_and_body;
148 header_and_body.SerializeToString(&serialized_header_and_body);
150 securemessage::SecureMessage secure_message;
151 secure_message.set_header_and_body(serialized_header_and_body);
152 secure_message.set_signature(
153 Sign(payload, create_options.associated_data, key));
155 std::string serialized_secure_message;
156 secure_message.SerializeToString(&serialized_secure_message);
157 callback.Run(serialized_secure_message);
160 void FakeSecureMessageDelegate::UnwrapSecureMessage(
161 const std::string& serialized_message,
162 const std::string& key,
163 const UnwrapOptions& unwrap_options,
164 const UnwrapSecureMessageCallback& callback) {
165 securemessage::SecureMessage secure_message;
166 if (!secure_message.ParseFromString(serialized_message)) {
167 LOG(ERROR) << "Failed to parse SecureMessage.";
168 callback.Run(false, std::string(), securemessage::Header());
169 return;
172 securemessage::HeaderAndBody header_and_body;
173 if (!header_and_body.ParseFromString(secure_message.header_and_body())) {
174 LOG(ERROR) << "Failed to parse secure message HeaderAndBody.";
175 callback.Run(false, std::string(), securemessage::Header());
176 return;
179 const securemessage::Header& header = header_and_body.header();
180 std::string payload =
181 Decrypt(header_and_body.body(), key, unwrap_options.encryption_scheme);
183 bool verified = Verify(secure_message.signature(), payload,
184 unwrap_options.associated_data, key,
185 unwrap_options.signature_scheme);
186 if (verified) {
187 callback.Run(true, payload, header);
188 } else {
189 callback.Run(false, std::string(), securemessage::Header());
193 std::string FakeSecureMessageDelegate::GetPrivateKeyForPublicKey(
194 const std::string& public_key) {
195 return kPrivateKeyPrefix + public_key;
198 } // namespace proximity_auth