Skip to content

Commit

Permalink
fix style, make cypher code inline, update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
everard committed Jan 27, 2015
1 parent 256c7d4 commit f12fd75
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 88 deletions.
2 changes: 1 addition & 1 deletion Build/Makefile
Expand Up @@ -2,7 +2,7 @@ CXX = g++

all:
@mkdir -p bin
$(CXX) -Wall -Wextra -O3 -frtti -std=c++11 ./../Source/Main.cpp ./../Source/Salsa20.cpp -o bin/salsa20
$(CXX) -Wall -Wextra -O3 -frtti -std=c++11 ./../Source/Main.cpp -o bin/salsa20

clean:
@rm -rf bin
Expand Down
2 changes: 1 addition & 1 deletion Build/Salsa20.cbp
Expand Up @@ -71,8 +71,8 @@
<Add option="-Wall" />
</Compiler>
<Unit filename="../Source/Main.cpp" />
<Unit filename="../Source/Salsa20.cpp" />
<Unit filename="../Source/Salsa20.h" />
<Unit filename="../Source/Salsa20.inl" />
<Extensions>
<code_completion />
<envvars />
Expand Down
30 changes: 16 additions & 14 deletions README.md
Expand Up @@ -7,33 +7,35 @@ Salsa20 home page: http://cr.yp.to/snuffle.html
HOW TO USE
==========

1. Add Salsa20.h and Salsa20.cpp files to your project.
2. In your C++ code you should initialize cypher with key and IV:
1. Add Salsa20.h and Salsa20.inl files to your project.
2. In your C++ code initialize cypher with secret key and IV:

salsa20::Cypher cypher(key);
cypher.setIv(iv);
ucstk::Salsa20 salsa20(key);
salsa20.setIv(iv);

3. Now you can use processBlocks member function to encrypt or decrypt blocks (size of the block equals to 64 bytes).
If you would like to process number of bytes not multiple of block size, then use processBytes member function.
3. Now you can use Salsa20::processBlocks to encrypt or decrypt blocks (size of the block equals to 64 bytes).
If you would like to process number of bytes not multiple of block size, then use Salsa20::processBytes.

cypher.processBlocks(input, output, numBlocks);
cypher.processBytes(input, output, numBytes);
salsa20.processBlocks(input, output, numBlocks);
salsa20.processBytes(input, output, numBytes);

Note that processBytes may only be used once (typically after consecutive calls to processBlocks member function).
Note that Salsa20::processBytes may only be used once (typically after consecutive calls to Salsa20::processBlocks).

4. You can also use cypher to generate key stream (which is basically a random 64 byte long value):
4. You can also use cypher to generate key stream (which is a random sequence of 64 bytes):

std::uint8_t keyStream[salsa20::Cypher::BLOCK_SIZE];
cypher.generateKeyStream(keyStream);
std::uint8_t keyStream[ucstk::Salsa20::BLOCK_SIZE];
salsa20.generateKeyStream(keyStream);

COMMAND LINE INTRFACE
=====================
Another option is to build command line utility which can encrypt and decrypt files:
This repository also contains command line utility which can encrypt and decrypt files. To build it you should run the following
commands in your shell:

make
sudo make install

And then use it like this:
Now you can view help on how to use this utility by typing the following command in your shell:

salsa20 -h

LICENSE
Expand Down
45 changes: 24 additions & 21 deletions Source/Main.cpp
@@ -1,4 +1,4 @@
// Copyright (c) 2014 Nezametdinov E. Ildus
// Copyright (c) 2015 Nezametdinov E. Ildus
// See LICENSE.TXT for licensing details

#include "Salsa20.h"
Expand All @@ -8,7 +8,7 @@
#include <fstream>
#include <string>

using namespace salsa20;
using namespace ucstk;

/**
* Represents program.
Expand Down Expand Up @@ -127,27 +127,27 @@ class Program
return false;
}

const size_t chunkSize = NUM_OF_BLOCKS_PER_CHUNK * Cypher::BLOCK_SIZE;
const uint32_t chunkSize = NUM_OF_BLOCKS_PER_CHUNK * Salsa20::BLOCK_SIZE;
uint8_t chunk[chunkSize];

// determine size of the file
inputStream.seekg(0, std::ios_base::end);
size_t fileSize = inputStream.tellg();
auto fileSize = inputStream.tellg();
inputStream.seekg(0, std::ios_base::beg);

// compute number of chunks and size of the remainder
size_t numChunks = fileSize / chunkSize;
size_t remainderSize = fileSize % chunkSize;
auto numChunks = fileSize / chunkSize;
auto remainderSize = fileSize % chunkSize;

// process file
Cypher cypher(key_);
cypher.setIv(&key_[IV_OFFSET]);
Salsa20 salsa20(key_);
salsa20.setIv(&key_[IV_OFFSET]);
std::cout << "Processing file \"" << inputFileName_ << '"' << std::endl;

for(size_t i = 0; i < numChunks; ++i)
for(decltype(numChunks) i = 0; i < numChunks; ++i)
{
inputStream.read(reinterpret_cast<char*>(chunk), sizeof(chunk));
cypher.processBlocks(chunk, chunk, NUM_OF_BLOCKS_PER_CHUNK);
salsa20.processBlocks(chunk, chunk, NUM_OF_BLOCKS_PER_CHUNK);
outputStream.write(reinterpret_cast<const char*>(chunk), sizeof(chunk));

float percentage = 100.0f * static_cast<float>(i + 1) / static_cast<float>(numChunks);
Expand All @@ -157,7 +157,7 @@ class Program
if(remainderSize != 0)
{
inputStream.read(reinterpret_cast<char*>(chunk), remainderSize);
cypher.processBytes(chunk, chunk, remainderSize);
salsa20.processBytes(chunk, chunk, remainderSize);
outputStream.write(reinterpret_cast<const char*>(chunk), remainderSize);
std::cout << "[100.00]";
}
Expand All @@ -168,17 +168,13 @@ class Program

private:
/// Helper constants
enum
enum: uint32_t
{
NUM_OF_BLOCKS_PER_CHUNK = 8192,
IV_OFFSET = Cypher::KEY_SIZE,
KEY_SIZE = Cypher::KEY_SIZE + Cypher::IV_SIZE
IV_OFFSET = Salsa20::KEY_SIZE,
KEY_SIZE = Salsa20::KEY_SIZE + Salsa20::IV_SIZE
};

std::string inputFileName_, outputFileName_;
uint8_t key_[KEY_SIZE];
bool shouldShowHelp_;

/**
* \brief Reads byte from string.
* \param[in] string string
Expand All @@ -189,7 +185,7 @@ class Program
{
byte = 0;

for(size_t i = 0; i < 2; ++i)
for(uint32_t i = 0; i < 2; ++i)
{
uint8_t value = 0;
char c = string[i];
Expand All @@ -216,10 +212,12 @@ class Program
*/
bool readKeyFromString(const std::string& string)
{
if(string.length() != 2 * KEY_SIZE)
auto stringLength = string.length();

if(stringLength != 2 * KEY_SIZE)
return false;

for(size_t i = 0; i < string.length(); i += 2)
for(decltype(stringLength) i = 0; i < stringLength; i += 2)
{
if(!readByte(&string[i], key_[i / 2]))
return false;
Expand All @@ -228,6 +226,11 @@ class Program
return true;
}

// Data members
std::string inputFileName_, outputFileName_;
uint8_t key_[KEY_SIZE];
bool shouldShowHelp_;

};

// Entry point
Expand Down
50 changes: 24 additions & 26 deletions Source/Salsa20.h
@@ -1,33 +1,29 @@
// Copyright (c) 2014 Nezametdinov E. Ildus
// Copyright (c) 2015 Nezametdinov E. Ildus
// See LICENSE.TXT for licensing details

#ifndef SALSA20_H
#define SALSA20_H

#include <cassert>
#include <climits>
#include <cstdint>
#include <cstring>

#if CHAR_BIT != 8
#error size of the byte should be 8 bits
#endif

namespace salsa20
namespace ucstk
{

using std::size_t;
using std::int32_t;
using std::uint8_t;
using std::uint32_t;

/**
* Represents Salsa20 cypher. Supports 256-bit keys.
* Represents Salsa20 cypher. Supports only 256-bit keys.
*/
class Cypher
class Salsa20
{
public:
/// Helper constants
enum
enum: uint32_t
{
VECTOR_SIZE = 16,
BLOCK_SIZE = 64,
Expand All @@ -39,38 +35,38 @@ namespace salsa20
* \brief Constructs cypher with given key.
* \param[in] key 256-bit key
*/
Cypher(const uint8_t* key = nullptr);
Cypher(const Cypher&) = default;
Cypher(Cypher&&) = default;
~Cypher() = default;
Cypher& operator =(const Cypher&) = default;
Cypher& operator =(Cypher&&) = default;
inline Salsa20(const uint8_t* key = nullptr);
Salsa20(const Salsa20&) = default;
Salsa20(Salsa20&&) = default;
~Salsa20() = default;
Salsa20& operator =(const Salsa20&) = default;
Salsa20& operator =(Salsa20&&) = default;

/**
* \brief Sets key.
* \param[in] key 256-bit key
*/
void setKey(const uint8_t* key);
inline void setKey(const uint8_t* key);

/**
* \brief Sets IV.
* \param[in] iv 64-bit IV
*/
void setIv(const uint8_t* iv);
inline void setIv(const uint8_t* iv);

/**
* \brief Generates key stream.
* \param[out] output generated key stream
*/
void generateKeyStream(uint8_t output[BLOCK_SIZE]);
inline void generateKeyStream(uint8_t output[BLOCK_SIZE]);

/**
* \brief Processes blocks.
* \param[in] input input
* \param[out] output output
* \param[in] numBlocks number of blocks
*/
void processBlocks(const uint8_t* input, uint8_t* output, size_t numBlocks);
inline void processBlocks(const uint8_t* input, uint8_t* output, uint32_t numBlocks);

/**
* \brief Processes bytes.
Expand All @@ -83,35 +79,37 @@ namespace salsa20
* \param[out] output output
* \param[in] numBytes number of bytes
*/
void processBytes(const uint8_t* input, uint8_t* output, size_t numBytes);
inline void processBytes(const uint8_t* input, uint8_t* output, uint32_t numBytes);

private:
uint32_t vector_[VECTOR_SIZE];

/**
* \brief Rotates value.
* \param[in] value value
* \param[in] numBits number of bits to rotate
* \return result of the rotation
*/
uint32_t rotate(uint32_t value, uint32_t numBits);
inline uint32_t rotate(uint32_t value, uint32_t numBits);

/**
* \brief Converts 32-bit unsigned integer value to the array of bytes.
* \param[in] value 32-bit unsigned integer value
* \param[out] array array of bytes
*/
void convert(uint32_t value, uint8_t* array);
inline void convert(uint32_t value, uint8_t* array);

/**
* \brief Converts array of bytes to the 32-bit unsigned integer value.
* \param[in] array array of bytes
* \return 32-bit unsigned integer value
*/
uint32_t convert(const uint8_t* array);
inline uint32_t convert(const uint8_t* array);

// Data members
uint32_t vector_[VECTOR_SIZE];

};

}

#include "Salsa20.inl"
#endif

0 comments on commit f12fd75

Please sign in to comment.