Skip to content

Commit

Permalink
Generate signature for Attributes. (envoyproxy#10)
Browse files Browse the repository at this point in the history
* Generate signature for Attributes.

* Add signature test.

* Address comments.
  • Loading branch information
chowchow316 authored Jan 20, 2017
1 parent 755b410 commit c02a5f5
Show file tree
Hide file tree
Showing 7 changed files with 398 additions and 0 deletions.
25 changes: 25 additions & 0 deletions mixerclient/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ cc_library(
"src/client_impl.cc",
"src/client_impl.h",
"src/stream_transport.h",
"src/signature.cc",
"src/signature.h",
"utils/md5.cc",
"utils/md5.h",
],
hdrs = [
"include/client.h",
Expand Down Expand Up @@ -80,3 +84,24 @@ cc_test(
"//external:googletest_main",
],
)

cc_test(
name = "md5_test",
size = "small",
srcs = ["utils/md5_test.cc"],
deps = [
":mixer_client_lib",
"//external:googletest_main",
],
)

cc_test(
name = "signature_test",
size = "small",
srcs = ["src/signature_test.cc"],
deps = [
":mixer_client_lib",
"//external:googletest_main",
],
)

67 changes: 67 additions & 0 deletions mixerclient/src/signature.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* Copyright 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "src/signature.h"
#include "utils/md5.h"

using std::string;
using ::istio::mixer::v1::CheckRequest;
using ::istio::mixer::v1::CheckResponse;

namespace istio {
namespace mixer_client {
namespace {
const char kDelimiter[] = "\0";
const int kDelimiterLength = 1;
} // namespace

string GenerateSignature(const Attributes& attributes) {
MD5 hasher;

for (const auto& attribute : attributes.attributes) {
hasher.Update(attribute.first);
hasher.Update(kDelimiter, kDelimiterLength);
switch (attribute.second.type) {
case Attributes::Value::ValueType::STRING:
hasher.Update(attribute.second.str_v);
break;
case Attributes::Value::ValueType::BYTES:
hasher.Update(attribute.second.str_v);
break;
case Attributes::Value::ValueType::INT64:
hasher.Update(&attribute.second.value.int64_v,
sizeof(attribute.second.value.int64_v));
break;
case Attributes::Value::ValueType::DOUBLE:
hasher.Update(&attribute.second.value.double_v,
sizeof(attribute.second.value.double_v));
break;
case Attributes::Value::ValueType::BOOL:
hasher.Update(&attribute.second.value.bool_v,
sizeof(attribute.second.value.bool_v));
break;
case Attributes::Value::ValueType::TIME:
hasher.Update(&attribute.second.time_v,
sizeof(attribute.second.time_v));
break;
}
hasher.Update(kDelimiter, kDelimiterLength);
}

return hasher.Digest();
}

} // namespace mixer_client
} // namespace istio
34 changes: 34 additions & 0 deletions mixerclient/src/signature.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* Copyright 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// Utility functions used to generate signature for operations, metric values,
// and check requests.

#ifndef MIXER_CLIENT_SIGNATURE_H_
#define MIXER_CLIENT_SIGNATURE_H_

#include <string>
#include "include/client.h"

namespace istio {
namespace mixer_client {

// Generates signature for Attributes.
std::string GenerateSignature(const Attributes& attributes);

} // namespace mixer_client
} // namespace istio

#endif // MIXER_CLIENT_SIGNATURE_H_
108 changes: 108 additions & 0 deletions mixerclient/src/signature_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/* Copyright 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "src/signature.h"
#include "utils/md5.h"

#include <time.h>
#include "google/protobuf/text_format.h"
#include "gtest/gtest.h"

using std::string;
using ::google::protobuf::TextFormat;

namespace istio {
namespace mixer_client {
namespace {

class SignatureUtilTest : public ::testing::Test {
protected:
void AddString(const string& key, const string& value) {
Attributes::Value string_value;
string_value.type = Attributes::Value::STRING;
string_value.str_v = value;
attributes_map_.attributes[key] = string_value;
}

void AddBytes(const string& key, const string& value) {
Attributes::Value bytes_value;
bytes_value.type = Attributes::Value::BYTES;
bytes_value.str_v = value;
attributes_map_.attributes[key] = bytes_value;
}

void AddTime(
const string& key,
const std::chrono::time_point<std::chrono::system_clock>& value) {
Attributes::Value time_value;
time_value.time_v = value;
attributes_map_.attributes[key] = time_value;
}

void AddDoublePair(const string& key, const double& value) {
Attributes::Value double_value;
double_value.type = Attributes::Value::DOUBLE;
double_value.value.double_v = value;
attributes_map_.attributes[key] = double_value;
}

void AddInt64Pair(const string& key, const int64_t& value) {
Attributes::Value int64_value;
int64_value.type = Attributes::Value::INT64;
int64_value.value.int64_v = value;
attributes_map_.attributes[key] = int64_value;
}

void AddBoolPair(const string& key, const bool& value) {
Attributes::Value bool_value;
bool_value.type = Attributes::Value::BOOL;
bool_value.value.bool_v = value;
attributes_map_.attributes[key] = bool_value;
}

Attributes attributes_map_;
};

TEST_F(SignatureUtilTest, Attributes) {
AddString("string-key", "this is a string value");
EXPECT_EQ("26f8f724383c46e7f5803380ab9c17ba",
MD5::DebugString(GenerateSignature(attributes_map_)));

AddBytes("bytes-key", "this is a bytes value");
EXPECT_EQ("1f409524b79b9b5760032dab7ecaf960",
MD5::DebugString(GenerateSignature(attributes_map_)));

AddDoublePair("double-key", 99.9);
EXPECT_EQ("6183342ff222018f6300de51cdcd4501",
MD5::DebugString(GenerateSignature(attributes_map_)));

AddInt64Pair("int-key", 35);
EXPECT_EQ("d681b9c72d648f9c831d95b4748fe1c2",
MD5::DebugString(GenerateSignature(attributes_map_)));

AddBoolPair("bool-key", true);
EXPECT_EQ("958930b41f0d8b43f5c61c31b0b092e2",
MD5::DebugString(GenerateSignature(attributes_map_)));

// default to Clock's epoch.
std::chrono::time_point<std::chrono::system_clock> time_point;
AddTime("time-key", time_point);
EXPECT_EQ("44953987f7424cecc6dc69ffb7a8bf86",
MD5::DebugString(GenerateSignature(attributes_map_)));
}

} // namespace
} // namespace mixer_client
} // namespace istio
55 changes: 55 additions & 0 deletions mixerclient/utils/md5.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* Copyright 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "md5.h"
#include <assert.h>

namespace istio {
namespace mixer_client {

MD5::MD5() : finalized_(false) { MD5_Init(&ctx_); }

MD5& MD5::Update(const void* data, size_t size) {
// Not update after finalized.
assert(!finalized_);
MD5_Update(&ctx_, data, size);
return *this;
}

std::string MD5::Digest() {
if (!finalized_) {
MD5_Final(digest_, &ctx_);
finalized_ = true;
}
return std::string(reinterpret_cast<char*>(digest_), kDigestLength);
}

std::string MD5::DebugString(const std::string& digest) {
assert(digest.size() == kDigestLength);
char buf[kDigestLength * 2 + 1];
char* p = buf;
for (int i = 0; i < kDigestLength; i++, p += 2) {
sprintf(p, "%02x", (unsigned char)digest[i]);
}
*p = 0;
return std::string(buf, kDigestLength * 2);
}

std::string MD5::operator()(const void* data, size_t size) {
return Update(data, size).Digest();
}

} // namespace mixer_client
} // namespace istio
68 changes: 68 additions & 0 deletions mixerclient/utils/md5.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* Copyright 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef MIXER_CLIENT_UTILS_MD5_H_
#define MIXER_CLIENT_UTILS_MD5_H_

#include <string.h>
#include <string>
#include "openssl/md5.h"

namespace istio {
namespace mixer_client {

// Define a MD5 Digest by calling OpenSSL
class MD5 {
public:
MD5();

// Updates the context with data.
MD5& Update(const void* data, size_t size);

// A helper function for const char*
MD5& Update(const char* str) { return Update(str, strlen(str)); }

// A helper function for const string
MD5& Update(const std::string& str) { return Update(str.data(), str.size()); }

// A helper function for int
MD5& Update(int d) { return Update(&d, sizeof(d)); }

// The MD5 digest is always 128 bits = 16 bytes
static const int kDigestLength = 16;

// Returns the digest as string.
std::string Digest();

// A short form of generating MD5 for a string
std::string operator()(const void* data, size_t size);

// Converts a binary digest string to a printable string.
// It is for debugging and unit-test only.
static std::string DebugString(const std::string& digest);

private:
// MD5 context.
MD5_CTX ctx_;
// The final MD5 digest.
unsigned char digest_[kDigestLength];
// A flag to indicate if MD5_final is called or not.
bool finalized_;
};

} // namespace mixer_client
} // namespace istio

#endif // MIXER_CLIENT_CLIENT_UTILS_MD5_H_
Loading

0 comments on commit c02a5f5

Please sign in to comment.