From 3f50c49924e86094e58addffb98123e20983f2d9 Mon Sep 17 00:00:00 2001 From: fireuse Date: Sun, 31 May 2020 20:30:33 +0200 Subject: [PATCH 1/2] Added SHA1 Signed-off-by: fireuse --- source/cppfs/CMakeLists.txt | 2 +- source/cppfs/source/SHA1.hpp | 215 +++++++++++++++++++++++++ source/tests/cppfs-test/cppfs_test.cpp | 6 +- 3 files changed, 221 insertions(+), 2 deletions(-) create mode 100644 source/cppfs/source/SHA1.hpp diff --git a/source/cppfs/CMakeLists.txt b/source/cppfs/CMakeLists.txt index 520512c..0d86c72 100644 --- a/source/cppfs/CMakeLists.txt +++ b/source/cppfs/CMakeLists.txt @@ -100,7 +100,7 @@ set(sources ${source_path}/Tree.cpp ${source_path}/Diff.cpp ${source_path}/Change.cpp - + ${source_path}/SHA1.hpp ${source_path}/${localfs}/LocalFileSystem.cpp ${source_path}/${localfs}/LocalFileHandle.cpp ${source_path}/${localfs}/LocalFileIterator.cpp diff --git a/source/cppfs/source/SHA1.hpp b/source/cppfs/source/SHA1.hpp new file mode 100644 index 0000000..9ab9a22 --- /dev/null +++ b/source/cppfs/source/SHA1.hpp @@ -0,0 +1,215 @@ +#ifndef CPPFS_SHA1_HPP +#define CPPFS_SHA1_HPP + +#include +#include +#include + + +inline static uint32_t rol(const uint32_t value, const size_t bits) { + return (value << bits) | (value >> (32 - bits)); +} + + +inline static uint32_t blk(const uint32_t block[16], const size_t i) { + return rol(block[(i + 13) & 15] ^ block[(i + 8) & 15] ^ block[(i + 2) & 15] ^ block[i], 1); +} + + +inline static void +R0(const uint32_t block[16], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, + const size_t i) { + z += ((w & (x ^ y)) ^ y) + block[i] + 0x5a827999 + rol(v, 5); + w = rol(w, 30); +} + + +inline static void +R1(uint32_t block[16], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) { + block[i] = blk(block, i); + z += ((w & (x ^ y)) ^ y) + block[i] + 0x5a827999 + rol(v, 5); + w = rol(w, 30); +} + + +inline static void +R2(uint32_t block[16], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) { + block[i] = blk(block, i); + z += (w ^ x ^ y) + block[i] + 0x6ed9eba1 + rol(v, 5); + w = rol(w, 30); +} + + +inline static void +R3(uint32_t block[16], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) { + block[i] = blk(block, i); + z += (((w | x) & y) | (w & x)) + block[i] + 0x8f1bbcdc + rol(v, 5); + w = rol(w, 30); +} + + +inline static void +R4(uint32_t block[16], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i) { + block[i] = blk(block, i); + z += (w ^ x ^ y) + block[i] + 0xca62c1d6 + rol(v, 5); + w = rol(w, 30); +} + +inline static void transform(uint32_t digest[], uint32_t block[16], uint64_t &transforms) { + uint32_t a = digest[0]; + uint32_t b = digest[1]; + uint32_t c = digest[2]; + uint32_t d = digest[3]; + uint32_t e = digest[4]; + R0(block, a, b, c, d, e, 0); + R0(block, e, a, b, c, d, 1); + R0(block, d, e, a, b, c, 2); + R0(block, c, d, e, a, b, 3); + R0(block, b, c, d, e, a, 4); + R0(block, a, b, c, d, e, 5); + R0(block, e, a, b, c, d, 6); + R0(block, d, e, a, b, c, 7); + R0(block, c, d, e, a, b, 8); + R0(block, b, c, d, e, a, 9); + R0(block, a, b, c, d, e, 10); + R0(block, e, a, b, c, d, 11); + R0(block, d, e, a, b, c, 12); + R0(block, c, d, e, a, b, 13); + R0(block, b, c, d, e, a, 14); + R0(block, a, b, c, d, e, 15); + R1(block, e, a, b, c, d, 0); + R1(block, d, e, a, b, c, 1); + R1(block, c, d, e, a, b, 2); + R1(block, b, c, d, e, a, 3); + R2(block, a, b, c, d, e, 4); + R2(block, e, a, b, c, d, 5); + R2(block, d, e, a, b, c, 6); + R2(block, c, d, e, a, b, 7); + R2(block, b, c, d, e, a, 8); + R2(block, a, b, c, d, e, 9); + R2(block, e, a, b, c, d, 10); + R2(block, d, e, a, b, c, 11); + R2(block, c, d, e, a, b, 12); + R2(block, b, c, d, e, a, 13); + R2(block, a, b, c, d, e, 14); + R2(block, e, a, b, c, d, 15); + R2(block, d, e, a, b, c, 0); + R2(block, c, d, e, a, b, 1); + R2(block, b, c, d, e, a, 2); + R2(block, a, b, c, d, e, 3); + R2(block, e, a, b, c, d, 4); + R2(block, d, e, a, b, c, 5); + R2(block, c, d, e, a, b, 6); + R2(block, b, c, d, e, a, 7); + R3(block, a, b, c, d, e, 8); + R3(block, e, a, b, c, d, 9); + R3(block, d, e, a, b, c, 10); + R3(block, c, d, e, a, b, 11); + R3(block, b, c, d, e, a, 12); + R3(block, a, b, c, d, e, 13); + R3(block, e, a, b, c, d, 14); + R3(block, d, e, a, b, c, 15); + R3(block, c, d, e, a, b, 0); + R3(block, b, c, d, e, a, 1); + R3(block, a, b, c, d, e, 2); + R3(block, e, a, b, c, d, 3); + R3(block, d, e, a, b, c, 4); + R3(block, c, d, e, a, b, 5); + R3(block, b, c, d, e, a, 6); + R3(block, a, b, c, d, e, 7); + R3(block, e, a, b, c, d, 8); + R3(block, d, e, a, b, c, 9); + R3(block, c, d, e, a, b, 10); + R3(block, b, c, d, e, a, 11); + R4(block, a, b, c, d, e, 12); + R4(block, e, a, b, c, d, 13); + R4(block, d, e, a, b, c, 14); + R4(block, c, d, e, a, b, 15); + R4(block, b, c, d, e, a, 0); + R4(block, a, b, c, d, e, 1); + R4(block, e, a, b, c, d, 2); + R4(block, d, e, a, b, c, 3); + R4(block, c, d, e, a, b, 4); + R4(block, b, c, d, e, a, 5); + R4(block, a, b, c, d, e, 6); + R4(block, e, a, b, c, d, 7); + R4(block, d, e, a, b, c, 8); + R4(block, c, d, e, a, b, 9); + R4(block, b, c, d, e, a, 10); + R4(block, a, b, c, d, e, 11); + R4(block, e, a, b, c, d, 12); + R4(block, d, e, a, b, c, 13); + R4(block, c, d, e, a, b, 14); + R4(block, b, c, d, e, a, 15); + digest[0] += a; + digest[1] += b; + digest[2] += c; + digest[3] += d; + digest[4] += e; + + transforms++; +} + + +inline static void buffer_to_block(const std::string &buffer, uint32_t block[16]) { + for (size_t i = 0; i < 16; i++) { + block[i] = (buffer[4 * i + 3] & 0xff) + | (buffer[4 * i + 2] & 0xff) << 8 + | (buffer[4 * i + 1] & 0xff) << 16 + | (buffer[4 * i + 0] & 0xff) << 24; + } +} + + +std::string sha1(std::istream &is) { + uint32_t digest[5]; + std::string buffer; + uint64_t transforms = 0; + digest[0] = 0x67452301; + digest[1] = 0xefcdab89; + digest[2] = 0x98badcfe; + digest[3] = 0x10325476; + digest[4] = 0xc3d2e1f0; + while (true) { + char sbuf[64]; + is.read(sbuf, 64 - buffer.size()); + buffer.append(sbuf, (std::size_t) is.gcount()); + if (buffer.size() != 64) { + break; + } + uint32_t block[16]; + buffer_to_block(buffer, block); + transform(digest, block, transforms); + buffer.clear(); + } + + uint64_t total_bits = (transforms * 64 + buffer.size()) * 8; + buffer += (char) 0x80; + size_t orig_size = buffer.size(); + while (buffer.size() < 64) { + buffer += (char) 0x00; + } + + uint32_t block[16]; + buffer_to_block(buffer, block); + + if (orig_size > 64 - 8) { + transform(digest, block, transforms); + for (size_t i = 0; i < 16 - 2; i++) { + block[i] = 0; + } + } + block[16 - 1] = (uint32_t) total_bits; + block[16 - 2] = (uint32_t) (total_bits >> 32); + transform(digest, block, transforms); + + std::ostringstream result; + for (unsigned int i : digest) { + result << std::hex << std::setfill('0') << std::setw(8); + result << i; + } + + return result.str(); +} + +#endif //CPPFS_SHA1_HPP \ No newline at end of file diff --git a/source/tests/cppfs-test/cppfs_test.cpp b/source/tests/cppfs-test/cppfs_test.cpp index 2864208..7bcdc6c 100644 --- a/source/tests/cppfs-test/cppfs_test.cpp +++ b/source/tests/cppfs-test/cppfs_test.cpp @@ -1,5 +1,6 @@ #include +#include "../../cppfs/source/SHA1.hpp" class cppfs_test: public testing::Test @@ -11,7 +12,10 @@ class cppfs_test: public testing::Test TEST_F(cppfs_test, CheckSomeResults) { // [TODO] Implement test - + std::stringstream t1(""); + std::stringstream t2("abc"); + EXPECT_EQ(sha1(t1),"da39a3ee5e6b4b0d3255bfef95601890afd80709"); + EXPECT_EQ(sha1(t2),"a9993e364706816aba3e25717850c26c9cd0d89d"); EXPECT_EQ((unsigned int) 0, 0); // ... } From d2d574b5e33a8f51ed50bf573534a19b0485d586 Mon Sep 17 00:00:00 2001 From: fireuse Date: Sun, 31 May 2020 20:53:50 +0200 Subject: [PATCH 2/2] Changed implementation of sha1 in filehandle Signed-off-by: fireuse --- source/cppfs/include/cppfs/fs.h | 12 --- source/cppfs/source/FileHandle.cpp | 33 +------- source/cppfs/source/SHA1.hpp | 100 +++++++++++++------------ source/cppfs/source/fs.cpp | 35 +-------- source/tests/cppfs-test/cppfs_test.cpp | 12 ++- 5 files changed, 67 insertions(+), 125 deletions(-) diff --git a/source/cppfs/include/cppfs/fs.h b/source/cppfs/include/cppfs/fs.h index b4dc003..d2cd9e3 100644 --- a/source/cppfs/include/cppfs/fs.h +++ b/source/cppfs/include/cppfs/fs.h @@ -83,18 +83,6 @@ CPPFS_API std::string base64(const std::string & str); */ CPPFS_API std::string fromBase64(const std::string & base64); -/** -* @brief -* Convert hash buffer into string -* -* @param[in] hash -* Hash buffer -* -* @return -* Hash string -*/ -CPPFS_API std::string hashToString(const unsigned char * hash); - } // namespace fs diff --git a/source/cppfs/source/FileHandle.cpp b/source/cppfs/source/FileHandle.cpp index 053f02c..9c41375 100644 --- a/source/cppfs/source/FileHandle.cpp +++ b/source/cppfs/source/FileHandle.cpp @@ -26,6 +26,7 @@ #include #include #include +#include "SHA1.hpp" namespace cppfs @@ -278,42 +279,12 @@ std::string FileHandle::sha1() const { return ""; } - -#ifdef CPPFS_USE_OpenSSL - // Open file auto inputStream = createInputStream(); if (!inputStream) { return ""; } - - // Initialize hash - unsigned char hash[20]; - SHA_CTX context; - SHA1_Init(&context); - - // Read whole while - while (!inputStream->eof()) - { - // Read a maximum of 1024 bytes at once - // Read data from file - std::array buf; - inputStream->read(buf.data(), buf.size()); - - size_t count = inputStream->gcount(); - if (count > 0) - { - // Update hash - SHA1_Update(&context, buf.data(), count); - } else break; - } - - // Compute hash - SHA1_Final(hash, &context); - return fs::hashToString(hash); -#else - return ""; -#endif + return fs::sha1digest(*inputStream); } std::string FileHandle::base64() const diff --git a/source/cppfs/source/SHA1.hpp b/source/cppfs/source/SHA1.hpp index 9ab9a22..228dd42 100644 --- a/source/cppfs/source/SHA1.hpp +++ b/source/cppfs/source/SHA1.hpp @@ -160,56 +160,58 @@ inline static void buffer_to_block(const std::string &buffer, uint32_t block[16] } } - -std::string sha1(std::istream &is) { - uint32_t digest[5]; - std::string buffer; - uint64_t transforms = 0; - digest[0] = 0x67452301; - digest[1] = 0xefcdab89; - digest[2] = 0x98badcfe; - digest[3] = 0x10325476; - digest[4] = 0xc3d2e1f0; - while (true) { - char sbuf[64]; - is.read(sbuf, 64 - buffer.size()); - buffer.append(sbuf, (std::size_t) is.gcount()); - if (buffer.size() != 64) { - break; - } - uint32_t block[16]; - buffer_to_block(buffer, block); - transform(digest, block, transforms); - buffer.clear(); - } - - uint64_t total_bits = (transforms * 64 + buffer.size()) * 8; - buffer += (char) 0x80; - size_t orig_size = buffer.size(); - while (buffer.size() < 64) { - buffer += (char) 0x00; - } - - uint32_t block[16]; - buffer_to_block(buffer, block); - - if (orig_size > 64 - 8) { - transform(digest, block, transforms); - for (size_t i = 0; i < 16 - 2; i++) { - block[i] = 0; +namespace cppfs { + namespace fs { + inline std::string sha1digest(std::istream &is) { + uint32_t digest[5]; + std::string buffer; + uint64_t transforms = 0; + digest[0] = 0x67452301; + digest[1] = 0xefcdab89; + digest[2] = 0x98badcfe; + digest[3] = 0x10325476; + digest[4] = 0xc3d2e1f0; + while (true) { + char sbuf[64]; + is.read(sbuf, 64 - buffer.size()); + buffer.append(sbuf, (std::size_t) is.gcount()); + if (buffer.size() != 64) { + break; + } + uint32_t block[16]; + buffer_to_block(buffer, block); + transform(digest, block, transforms); + buffer.clear(); + } + + uint64_t total_bits = (transforms * 64 + buffer.size()) * 8; + buffer += (char) 0x80; + size_t orig_size = buffer.size(); + while (buffer.size() < 64) { + buffer += (char) 0x00; + } + + uint32_t block[16]; + buffer_to_block(buffer, block); + + if (orig_size > 64 - 8) { + transform(digest, block, transforms); + for (size_t i = 0; i < 16 - 2; i++) { + block[i] = 0; + } + } + block[16 - 1] = (uint32_t) total_bits; + block[16 - 2] = (uint32_t) (total_bits >> 32); + transform(digest, block, transforms); + + std::ostringstream result; + for (unsigned int i : digest) { + result << std::hex << std::setfill('0') << std::setw(8); + result << i; + } + + return result.str(); } } - block[16 - 1] = (uint32_t) total_bits; - block[16 - 2] = (uint32_t) (total_bits >> 32); - transform(digest, block, transforms); - - std::ostringstream result; - for (unsigned int i : digest) { - result << std::hex << std::setfill('0') << std::setw(8); - result << i; - } - - return result.str(); } - #endif //CPPFS_SHA1_HPP \ No newline at end of file diff --git a/source/cppfs/source/fs.cpp b/source/cppfs/source/fs.cpp index dbb1470..6fee413 100644 --- a/source/cppfs/source/fs.cpp +++ b/source/cppfs/source/fs.cpp @@ -4,7 +4,7 @@ #include #include #include - +#include "SHA1.hpp" #include #if defined(__APPLE__) @@ -13,7 +13,6 @@ #define SHA1 CC_SHA1 #include #elif defined(CPPFS_USE_OpenSSL) - #include #include #endif @@ -28,6 +27,7 @@ #include #else #include + #endif @@ -102,21 +102,8 @@ FileHandle open(const std::string & path, const LoginCredentials * credentials) std::string sha1(const std::string & str) { -#ifdef CPPFS_USE_OpenSSL - // Initialize hash - unsigned char hash[20]; - SHA_CTX context; - SHA1_Init(&context); - - // Update hash - SHA1_Update(&context, str.c_str(), str.size()); - - // Compute hash - SHA1_Final(hash, &context); - return hashToString(hash); -#else - return ""; -#endif + std::istringstream s(str); + return sha1digest(s); } std::string base64(const std::string & str) @@ -139,19 +126,5 @@ std::string fromBase64(const std::string & base64) return str; } -std::string hashToString(const unsigned char * hash) -{ - std::stringstream stream; - stream << std::hex << std::setfill('0') << std::setw(2); - - for (int i=0; i<20; i++) - { - stream << static_cast(hash[i]); - } - - return stream.str(); -} - - } // namespace fs } // namespace cppfs diff --git a/source/tests/cppfs-test/cppfs_test.cpp b/source/tests/cppfs-test/cppfs_test.cpp index 7bcdc6c..6682ff9 100644 --- a/source/tests/cppfs-test/cppfs_test.cpp +++ b/source/tests/cppfs-test/cppfs_test.cpp @@ -1,5 +1,7 @@ #include +#include +#include #include "../../cppfs/source/SHA1.hpp" @@ -14,8 +16,14 @@ TEST_F(cppfs_test, CheckSomeResults) // [TODO] Implement test std::stringstream t1(""); std::stringstream t2("abc"); - EXPECT_EQ(sha1(t1),"da39a3ee5e6b4b0d3255bfef95601890afd80709"); - EXPECT_EQ(sha1(t2),"a9993e364706816aba3e25717850c26c9cd0d89d"); + EXPECT_EQ(cppfs::fs::sha1digest(t1),"da39a3ee5e6b4b0d3255bfef95601890afd80709"); + EXPECT_EQ(cppfs::fs::sha1digest(t2),"a9993e364706816aba3e25717850c26c9cd0d89d"); + cppfs::FileHandle fileHandle = cppfs::fs::open("test.txt"); + fileHandle.remove(); + (*fileHandle.createOutputStream()) << "abc"; + fileHandle.updateFileInfo(); + EXPECT_EQ(fileHandle.sha1(),"a9993e364706816aba3e25717850c26c9cd0d89d"); + fileHandle.remove(); EXPECT_EQ((unsigned int) 0, 0); // ... }