Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removed dependency on openssl SHA1 implementation #35

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion source/cppfs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 0 additions & 12 deletions source/cppfs/include/cppfs/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
33 changes: 2 additions & 31 deletions source/cppfs/source/FileHandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <cppfs/AbstractFileSystem.h>
#include <cppfs/AbstractFileHandleBackend.h>
#include <cppfs/AbstractFileIteratorBackend.h>
#include "SHA1.hpp"


namespace cppfs
Expand Down Expand Up @@ -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<char, 1024> 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
Expand Down
217 changes: 217 additions & 0 deletions source/cppfs/source/SHA1.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
#ifndef CPPFS_SHA1_HPP
#define CPPFS_SHA1_HPP

#include <istream>
#include <iomanip>
#include <sstream>


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;
}
}

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();
}
}
}
#endif //CPPFS_SHA1_HPP
35 changes: 4 additions & 31 deletions source/cppfs/source/fs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <sstream>
#include <iomanip>
#include <iterator>

#include "SHA1.hpp"
#include <basen/basen.hpp>

#if defined(__APPLE__)
Expand All @@ -13,7 +13,6 @@
#define SHA1 CC_SHA1
#include <cppfs/ssh/SshFileSystem.h>
#elif defined(CPPFS_USE_OpenSSL)
#include <openssl/sha.h>
#include <cppfs/ssh/SshFileSystem.h>
#endif

Expand All @@ -28,6 +27,7 @@
#include <cppfs/windows/LocalFileSystem.h>
#else
#include <cppfs/posix/LocalFileSystem.h>

#endif


Expand Down Expand Up @@ -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)
Expand All @@ -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<unsigned int>(hash[i]);
}

return stream.str();
}


} // namespace fs
} // namespace cppfs
14 changes: 13 additions & 1 deletion source/tests/cppfs-test/cppfs_test.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@

#include <gmock/gmock.h>
#include <cppfs/fs.h>
#include <cppfs/FileHandle.h>
#include "../../cppfs/source/SHA1.hpp"


class cppfs_test: public testing::Test
Expand All @@ -11,7 +14,16 @@ class cppfs_test: public testing::Test
TEST_F(cppfs_test, CheckSomeResults)
{
// [TODO] Implement test

std::stringstream t1("");
std::stringstream t2("abc");
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);
// ...
}