Compare commits
No commits in common. "master" and "v0.12" have entirely different histories.
56
.drone.yml
@ -1,56 +0,0 @@
|
||||
kind: pipeline
|
||||
type: kubernetes
|
||||
name: cicd-pipeline
|
||||
|
||||
steps:
|
||||
- name: Build docs
|
||||
image: ubuntu
|
||||
commands:
|
||||
- apt-get update
|
||||
- >-
|
||||
apt-get
|
||||
install
|
||||
make
|
||||
doxygen
|
||||
graphviz
|
||||
-y
|
||||
- cd "GCryptLib/doxygen"
|
||||
- make
|
||||
|
||||
- name: Deploy docs to production
|
||||
image: ubuntu
|
||||
environment:
|
||||
SSH_PRIV:
|
||||
from_secret: ssh-priv
|
||||
SSH_PUB:
|
||||
from_secret: ssh-pub
|
||||
KNOWN_HOSTS:
|
||||
from_secret: known-hosts # this is just $(ssh-keyscan -p 2222 leonetienne.de)
|
||||
commands:
|
||||
- apt-get update
|
||||
- >-
|
||||
apt-get
|
||||
install
|
||||
openssh-client
|
||||
rsync
|
||||
-y
|
||||
- eval "$(ssh-agent -s)"
|
||||
- mkdir -p ~/.ssh
|
||||
- echo "$SSH_PRIV" > ~/.ssh/id_ed25519
|
||||
- echo "$SSH_PUB" > ~/.ssh/id_ed25519.pub
|
||||
- echo "$KNOWN_HOSTS" > ~/.ssh/known_hosts
|
||||
- chmod 600 ~/.ssh/id_ed25519
|
||||
- chmod 644 ~/.ssh/id_ed25519.pub
|
||||
- chmod 644 ~/.ssh/known_hosts
|
||||
- ssh-add
|
||||
- cd "GCryptLib/doxygen"
|
||||
- >-
|
||||
rsync
|
||||
-avz
|
||||
--recursive
|
||||
--delete
|
||||
--delete-excluded
|
||||
-e
|
||||
"ssh -o IdentitiesOnly=yes -p 2222"
|
||||
./build/
|
||||
doxygen-gcrypt@leonetienne.de:app
|
362
.gitignore
vendored
@ -1,4 +1,360 @@
|
||||
build/
|
||||
*.swp
|
||||
*_/
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
#infilename-tag
|
||||
*_gitignore_*
|
||||
|
||||
*.jpg
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Visual Paradigm Shitfiles
|
||||
*tornado.vpp.bak*
|
||||
*tornado.*lck*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
|
17
.gitmodules
vendored
@ -1,17 +0,0 @@
|
||||
[submodule "StringTools"]
|
||||
path = StringTools
|
||||
url = https://code.ze.mawtrixx.net/leonetienne/StringTools.git
|
||||
[submodule "Hazelnupp"]
|
||||
path = Hazelnupp
|
||||
url = https://code.ze.mawtrixx.net/leonetienne/Hazelnupp.git
|
||||
[submodule "GeneralUtility"]
|
||||
path = GeneralUtility
|
||||
url = https://code.ze.mawtrixx.net/leonetienne/GeneralUtility.git
|
||||
[submodule "GCryptLib/exec/Eule"]
|
||||
path = GCryptLib/exec/Eule
|
||||
url = https://code.ze.mawtrixx.net/leonetienne/Eule.git
|
||||
[submodule "GCryptLib/exec/BmpPP"]
|
||||
path = GCryptLib/exec/BmpPP
|
||||
url = https://code.ze.mawtrixx.net/leonetienne/BmpPP.git
|
||||
[submodule "BmpPP"]
|
||||
url = https://code.ze.mawtrixx.net/leonetienne/BmpPP.git
|
156
ExampleApp/ExampleApp.vcxproj
Normal file
@ -0,0 +1,156 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{b9a390ac-f382-42e6-92dd-3321293e7c27}</ProjectGuid>
|
||||
<RootNamespace>ExampleApp</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(SolutionDir)/GhettoCrypt;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(SolutionDir)/GhettoCrypt;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(SolutionDir)/GhettoCrypt;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(SolutionDir)/GhettoCrypt;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\GhettoCrypt\GhettoCrypt.vcxproj">
|
||||
<Project>{2b2cf665-f5e6-44db-961f-fc81c88a356d}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
22
ExampleApp/ExampleApp.vcxproj.filters
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Quelldateien">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Headerdateien">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Ressourcendateien">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Quelldateien</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
46
ExampleApp/main.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <GhettoCryptWrapper.h>
|
||||
#include <SecureBitset.h>
|
||||
|
||||
using namespace GhettoCipher;
|
||||
|
||||
void ExampleString()
|
||||
{
|
||||
std::cout << "Example on how to encrypt & decrypt a string:" << std::endl;
|
||||
|
||||
// Get some string
|
||||
const std::string input = "I am a super secret message!";
|
||||
std::cout << input << std::endl;
|
||||
|
||||
// Encrypt
|
||||
const std::string encrypted = GhettoCryptWrapper::EncryptString(input, "password1");
|
||||
std::cout << encrypted << std::endl;
|
||||
|
||||
// Decrypt
|
||||
const std::string decrypted = GhettoCryptWrapper::DecryptString(encrypted, "password1");
|
||||
std::cout << decrypted << std::endl;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void ExampleFiles()
|
||||
{
|
||||
std::cout << "Example on how to encrypt & decrypt any file:" << std::endl;
|
||||
|
||||
// Encrypt
|
||||
GhettoCryptWrapper::EncryptFile("main.cpp", "main.cpp.crypt", "password1");
|
||||
|
||||
// Decrypt
|
||||
GhettoCryptWrapper::DecryptFile("main.cpp.crypt", "main.cpp.clear", "password1");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
ExampleString();
|
||||
//ExampleFiles();
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(gcrypt)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# Add library StringTools
|
||||
SET(stringtools_dir ../StringTools/StringTools)
|
||||
SET(stringtools_include ${stringtools_dir}/include)
|
||||
FILE(GLOB stringtools_src ${stringtools_dir}/src/*.cpp)
|
||||
|
||||
# Add library GeneralUtility
|
||||
SET(generalutility_dir ../GeneralUtility/GeneralUtility)
|
||||
SET(generalutility_include ${generalutility_dir}/include)
|
||||
FILE(GLOB generalutility_src ${generalutility_dir}/src/*.cpp)
|
||||
|
||||
# Add library Hazelnupp
|
||||
SET(hazelnupp_dir ../Hazelnupp/Hazelnupp)
|
||||
SET(hazelnupp_include ${hazelnupp_dir}/include)
|
||||
FILE(GLOB hazelnupp_src ${hazelnupp_dir}/src/*.cpp)
|
||||
|
||||
# Add library GCrypt
|
||||
SET(gcrypt_dir ../GCryptLib)
|
||||
SET(gcrypt_include ${gcrypt_dir}/include)
|
||||
FILE(GLOB gcrypt_src ${gcrypt_dir}/src/*.cpp)
|
||||
|
||||
FILE(GLOB main_src src/*.cpp)
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
${main_src}
|
||||
|
||||
${stringtools_src}
|
||||
${generalutility_src}
|
||||
${hazelnupp_src}
|
||||
${gcrypt_src}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
include
|
||||
${stringtools_include}
|
||||
${generalutility_include}
|
||||
${hazelnupp_include}
|
||||
${gcrypt_include}
|
||||
)
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE
|
||||
-Werror
|
||||
-fdiagnostics-color=always
|
||||
)
|
||||
|
||||
#########
|
||||
# Tests #
|
||||
#########
|
||||
LIST(FILTER main_src EXCLUDE REGEX ".*/main.cpp")
|
||||
FILE(GLOB test_src test/*.cpp)
|
||||
|
||||
add_executable(test
|
||||
test/Catch2.h
|
||||
${test_src}
|
||||
${main_src}
|
||||
${stringtools_src}
|
||||
${generalutility_src}
|
||||
${hazelnupp_src}
|
||||
${gcrypt_src}
|
||||
)
|
||||
|
||||
target_include_directories(test PRIVATE
|
||||
include
|
||||
${stringtools_include}
|
||||
${generalutility_include}
|
||||
${hazelnupp_include}
|
||||
${gcrypt_include}
|
||||
)
|
||||
|
||||
target_compile_options(test PRIVATE
|
||||
-Werror
|
||||
-fdiagnostics-color=always
|
||||
)
|
||||
|
@ -1 +0,0 @@
|
||||
<mxfile host="app.diagrams.net" modified="2022-05-17T08:55:29.265Z" agent="5.0 (X11)" etag="82noNgqBrG7hiBNRM9Jy" version="18.0.6"><diagram id="ngb83caThQZh03zxjPih" name="Page-1">7VpNc+I4EP01VJHDUDYEkhwDJDvMMMXWcNjZuWwJq7G1sS2PLALk169alr9hQwhkApULltpS66Pfe2q5aHQGweoPQSLvG6fgN9oWXTU6w0a7bXdvLPVAyzqxXHdvEoMrGDWNcsOUPYExmn7uglGISw0l575kUdno8DAER5ZsRAi+LDebc788akRcqBmmDvHr1r8YlV66Ciu3fwbmeunItmXeBCRtbAyxRyhfFkydu0ZnIDiXSSlYDcDHzUv3Jel3v+VtNjEBodylw7/Bl88/u/F0YP9Yj9rf5uLrl+4n4+WR+Auz4Ea75yt/fcoeVdHF4pBIgo5CF2LJeKjKPlmDUM/mcDS+SLvMRNojtajZFPyUXFvEZ26ox+z9WuAm9H2Yy7xW7XUc79+B0Fi1748ng6//TEc/71RlxiTa5oIH6CrUi48WEhc8Zwoa7QEGVFIWJkUi3PjCFEOKzYMAKCMS/DU6AtCDSI/hY+Zz50EDWduUO2s4HLfU4ztEQPTYi1AyjN7d5B7doUkAcTyg2G5MYllwpF9LwvyIUAo4/pIp9LUtq3XKsbn1Y67XHUc8jNkMN14xGHFHnF8LJhQi0/hA6Ih1ZND5AOuTXvho3kAyJ11Zap0t5nMQowSI2WAsHyrBQa2fFIrbGzsMcvyNxho1WjFCLg1o9e6uFWz1RqeYhEcQmdEjmiosZLGnOyiYKl64+wXgpburhVWuU7UWfBEiATpDS71eekzCNCIOvl2q80nZPBn4qmarolqFZErpb01UJI8yn/gOVluV1s70Wx18wAOQAnmedrg0km/OPLtn6sv8BOmmJ4hXPD06xkjMqeVmvnNhVwWj7S/Q+c4LdJ6yTTo/zHX+gPHbix0hk0w1fgJEHs7YYZGnp6mRiaBmAaJ6iT8zcFGmrUhwB+LYaAbCHJYauVpWmrnXKbbi4UXrkJO+K88sU31NGAfYY7YYI+rITSZzUs4gC42mWdMoHlbuKeRlRUhFxF2CtfPkN59pNFHjJRG0cphNxnqCKwcimUk2zktv/kCjXmQBCo3QJMvE1ccX70a+T0JgOle7Cox1LIG5fIHA8IVMkqlcXSbvRl02E3XyQqIuBZMSwpQXoNIxvVKVM3JcOnZKEhkjQQcVm9+XnUxMaA+dnkxq6QnuMJTyk0EhRdEBMfGimRu/nDY373XWkuq9smyNwknIQEb5Z2XAPpYMdDfIQGXvIKS3eDFXNUcFJGZOebvKewsrJn9gudU1tb9NOywPV4Vmw7WpJEMCrd3sKxurpsUXwoHn78dSXfBAPpdf1QNVDMSGOKQ2AT6RCqnlrxcbYmNG+JOzUOY46FxXjoNqGpks0/QqfiKoOqoCql1xlOxDzZGGSrbs/dHTq6HnXuUGzT7y9aIOJBXgMZmBX8ZPKmOOCrbS3Dr/AkYp+uiriyV7IjPtD3ET4br0Srv9Rnf4fyQ1n5tM5/wjTxFj2wmyldGfrFan23sdKNImfD6P4Shhujolkv82UtplLrVv9iWlvSXZe4aUav/JutDMoHvnCacqkoMn8XhQKF3XoFS7hzUfYH0m5L86A/LffJD/efJnB+dryV91dCzy18Z5C/KnglM874sZefNMaH9zBrS3N31B/OB9hUaX9mXrqldi0mWVsbtSf4Ov7DL3Rvm4Xf+qc3YJub3l6nZa7Dype/d7Scn3pmbV0a68fG1K3rXf4lSu38LPOSe3z+FGbn9cyffIyvfmf9XRsfhfG+dN+F+/k59lVm6/79u4qub/DUua5/+w69z9Bw==</diagram></mxfile>
|
Before Width: | Height: | Size: 25 KiB |
@ -1,24 +0,0 @@
|
||||
* Add a new iobase: bytes.
|
||||
For cleartext:
|
||||
Format is ALWAYS raw bytes. That works fine with text, and files.
|
||||
The iobase ONLY affects ciphertext!
|
||||
|
||||
For ciphertext:
|
||||
format depends..:
|
||||
|
||||
If none specified:
|
||||
- raw bytes if an outputfile is given
|
||||
- hex if output to stdout
|
||||
|
||||
If specified:
|
||||
Just use the specified iobase. Even if it means dumping bytes to stdout, or writing base-2 to files.
|
||||
|
||||
|
||||
* --intext or --infile should no longer be required. Default behaviour should be reading from stdin.
|
||||
* No guessing where to output (like file-in got saved to another file beforehand.) Default behaviour should be stdout.
|
||||
|
||||
* --progress should output reports to stderr. This way it won't disturb piping the ciphertext to another program.
|
||||
|
||||
* Add a module to generate keyfiles.
|
||||
Should seed a gcrypt prng with std::random_device, and then dump BLOCK_SIZE bits to the specified output.
|
||||
|
@ -1,143 +0,0 @@
|
||||
#ifndef GCRYPTCLI_BASES_H
|
||||
#define GCRYPTCLI_BASES_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
// This lookup table holds how many digits a block is long
|
||||
// in any iobase.
|
||||
// This cannot be calculated on the fly, as it involves
|
||||
// arithmetic with involving REALLY big numbers (like, 2^512).
|
||||
// Here's how to calculate these numbers:
|
||||
// Print an all 1's block in this format, and check the string size.
|
||||
// That's it.
|
||||
static auto blockLengthByBase =
|
||||
std::map<Configuration::IOBASE_FORMAT, std::size_t>({
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_BYTES, 64),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_2, 512),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_8, 171),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_10, 155),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_16, 128),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_64, 86),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_UWU, 81),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_UGH, 126)
|
||||
});
|
||||
|
||||
// Actually useful bases
|
||||
static const std::vector<std::string> BASE_2 = { "0","1" };
|
||||
static const std::vector<std::string> BASE_8 = { "0","1","2","3","4","5","6","7"};
|
||||
static const std::vector<std::string> BASE_10 = { "0","1","2","3","4","5","6","7","8","9" };
|
||||
static const std::vector<std::string> BASE_64 = { "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/" };
|
||||
|
||||
// Fun bases
|
||||
static const std::vector<std::string> BASE_UWU = {
|
||||
"uwu",
|
||||
"UwU",
|
||||
"<3",
|
||||
":P",
|
||||
":p",
|
||||
":o",
|
||||
":O",
|
||||
":3",
|
||||
":)",
|
||||
"^.^",
|
||||
"^_^",
|
||||
"^^",
|
||||
"XD",
|
||||
"XDD",
|
||||
"XDDD",
|
||||
"xD",
|
||||
"xDD",
|
||||
"xDDD",
|
||||
"(*^.^*)",
|
||||
"(*^_^*)",
|
||||
"devewopa",
|
||||
"cutieee",
|
||||
"cutieees",
|
||||
"cutewr",
|
||||
"whiiiich",
|
||||
"masta",
|
||||
"mastaaaa",
|
||||
"hiiiii",
|
||||
"hewwo",
|
||||
"soopa",
|
||||
"doopa",
|
||||
"favowite",
|
||||
"kawaii",
|
||||
"rawr",
|
||||
"keewl",
|
||||
"keeeewl",
|
||||
"Owww",
|
||||
"Awww",
|
||||
"haaaai",
|
||||
"haaaay",
|
||||
"heeeey",
|
||||
"heeeei",
|
||||
"senpaiiii",
|
||||
"i",
|
||||
"nyeed",
|
||||
"awe",
|
||||
"youuu",
|
||||
"twe",
|
||||
"best",
|
||||
"ruff",
|
||||
"me",
|
||||
"nyeko",
|
||||
"eughh",
|
||||
"snaffle",
|
||||
"toot",
|
||||
"whiffle",
|
||||
"nappies",
|
||||
"chiffchaff",
|
||||
"kawaiisu",
|
||||
"*winks*",
|
||||
"*bites-lip*",
|
||||
"*blushes*",
|
||||
"*stutters*",
|
||||
"*sweats*",
|
||||
"uhh?!",
|
||||
"uhh..?",
|
||||
"nu-uh...",
|
||||
"sweatr",
|
||||
"comfy-womfy",
|
||||
"oopsie-whoopsie",
|
||||
"dewicious",
|
||||
"tastieee",
|
||||
"tasties",
|
||||
"boop",
|
||||
"smoochies",
|
||||
"whiffskaws",
|
||||
"chomp",
|
||||
"toesy-woesies",
|
||||
"smush",
|
||||
"snuff",
|
||||
"sniff",
|
||||
"snaff",
|
||||
"nyoo!",
|
||||
"nyah!",
|
||||
};
|
||||
|
||||
// Source: https://lakinkonieczny.wordpress.com/2012/12/06/dialogue-noises-agh-ugh-shh-and-so-much-more/
|
||||
static const std::vector<std::string> BASE_UGH = {
|
||||
"Agh!",
|
||||
"Ugh",
|
||||
"Shh!",
|
||||
"Pft!",
|
||||
"Aah!",
|
||||
"Uaah!",
|
||||
"Gah!",
|
||||
"Grr...",
|
||||
"Duh!",
|
||||
"Psh!",
|
||||
"Ah...",
|
||||
"Er-",
|
||||
"Huh...?",
|
||||
"Uh-huh...",
|
||||
"Nu-uh...",
|
||||
"Bah!",
|
||||
"Wha-?"
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,26 +0,0 @@
|
||||
#ifndef GCRYPTCLI_CLIINTERFACE_H
|
||||
#define GCRYPTCLI_CLIINTERFACE_H
|
||||
|
||||
#include <Hazelnupp/CmdArgsInterface.h>
|
||||
|
||||
class CommandlineInterface
|
||||
{
|
||||
public:
|
||||
static void Init(const int argc, const char* const* argv);
|
||||
|
||||
static Hazelnp::CmdArgsInterface& Get();
|
||||
|
||||
private:
|
||||
//! Special command compatibility checking unique to this app
|
||||
static void SpecialCompatibilityChecking();
|
||||
static void CrashWithMsg(const std::string& msg);
|
||||
static void CatchVersionQueries();
|
||||
|
||||
static Hazelnp::CmdArgsInterface nupp;
|
||||
|
||||
// No instanciation! >:(
|
||||
CommandlineInterface() {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,61 +0,0 @@
|
||||
#ifndef GCRYPTCLI_CONFIGURATION_H
|
||||
#define GCRYPTCLI_CONFIGURATION_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class Configuration {
|
||||
public:
|
||||
static enum class INPUT_FROM {
|
||||
STDIN,
|
||||
FILE,
|
||||
PARAMETER
|
||||
} inputFrom;
|
||||
|
||||
static enum class OUTPUT_TO {
|
||||
STDOUT,
|
||||
FILE
|
||||
} outputTo;
|
||||
|
||||
static enum class IOBASE_FORMAT {
|
||||
BASE_BYTES,
|
||||
BASE_2,
|
||||
BASE_8,
|
||||
BASE_10,
|
||||
BASE_16,
|
||||
BASE_64,
|
||||
BASE_UWU,
|
||||
BASE_UGH
|
||||
}
|
||||
formatIn,
|
||||
formatOut;
|
||||
|
||||
static std::string inputFilename;
|
||||
static std::string outputFilename;
|
||||
|
||||
static enum class MODULE {
|
||||
ENCRYPTION,
|
||||
DECRYPTION,
|
||||
HASH,
|
||||
GENERATE_KEY
|
||||
} activeModule;
|
||||
|
||||
//! Will analyze the supplied cli parameters,
|
||||
//! and decide what the configuration will be.
|
||||
static void Parse();
|
||||
|
||||
private:
|
||||
static void DecideInputFrom();
|
||||
static void DecideOutputTo();
|
||||
static void DecideCiphertextFormat();
|
||||
static void MapCiphertextFormatToIOBases();
|
||||
static void DecideModule();
|
||||
|
||||
// This is just an intermediary value, used between methods
|
||||
static IOBASE_FORMAT ciphertextFormat;
|
||||
|
||||
// No instanciation! >:(
|
||||
Configuration() {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,58 +0,0 @@
|
||||
#ifndef GCRYPTCLI_DATAFORMATTER_H
|
||||
#define GCRYPTCLI_DATAFORMATTER_H
|
||||
|
||||
#include <GCrypt/Block.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Configuration.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
// This class has the task to format Blocks to various formats.
|
||||
class DataFormatter {
|
||||
public:
|
||||
//! Will format a single block to a given iobase
|
||||
static std::string FormatBlock(
|
||||
const Block& block,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
);
|
||||
|
||||
//! Will parse a string of a given iobase to a block
|
||||
static Block DecodeFormat(
|
||||
const std::string& str,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
);
|
||||
|
||||
//! Will format a vector of blocks to a given iobase
|
||||
static std::string FormatBlocks(
|
||||
const std::vector<Block>& blocks,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
);
|
||||
|
||||
//! Will format a string making up multiple block in a given iobase into a vector of block
|
||||
static std::vector<Block> DecodeFormatMultiblock(
|
||||
const std::string& str,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
);
|
||||
|
||||
|
||||
private:
|
||||
static std::string Bin2CustomBase(
|
||||
const std::string& bin,
|
||||
const std::vector<std::string>& customSet,
|
||||
const std::size_t minLen,
|
||||
const std::string& seperator = ""
|
||||
);
|
||||
|
||||
static std::string CustomBase2Bin(
|
||||
const std::string& in,
|
||||
const std::vector<std::string>& customSet,
|
||||
const std::string& seperator = ""
|
||||
);
|
||||
|
||||
// No instanciation! >:(
|
||||
DataFormatter() {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,75 +0,0 @@
|
||||
#ifndef GCRYPTCLI_DATAINGESTIONLAYER_H
|
||||
#define GCRYPTCLI_DATAINGESTIONLAYER_H
|
||||
|
||||
#include <iosfwd>
|
||||
#include <queue>
|
||||
#include <GCrypt/Block.h>
|
||||
#include "Configuration.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
namespace IO {
|
||||
|
||||
// This class is used to read in data.
|
||||
class DataIngestionLayer {
|
||||
public:
|
||||
//! Will initialize the ingestion
|
||||
static void Init();
|
||||
|
||||
//! Will destruct the ingestion layer (like, closing file handles)
|
||||
static void Destruct();
|
||||
|
||||
//! Will attempt to read a data block.
|
||||
//! Requires Init() to have been called
|
||||
static void ReadBlock();
|
||||
|
||||
//! Have we read in all available blocks?
|
||||
static bool ReachedEOF();
|
||||
|
||||
//! Returns true if there are blocks to be fetched (GetNextBlock())
|
||||
static bool IsBlockReady();
|
||||
|
||||
//! Will return the next block in the queue
|
||||
static Block GetNextBlock();
|
||||
|
||||
//! Returns true, if EOF is reached, and there are no more blocks to fetch (GetNextBlock())
|
||||
static bool IsFinished();
|
||||
|
||||
//! Returns how many blocks have been read, in total
|
||||
static std::size_t NBlocksRead();
|
||||
|
||||
private:
|
||||
static std::istream* in;
|
||||
|
||||
// Will read n bytes from the input.
|
||||
// If EOF is reached, it will return a string of length <= 5
|
||||
// and will set the approriate flags.
|
||||
static std::string ReadBytes(const std::size_t n, std::size_t& out_bytes_read);
|
||||
|
||||
// We have to hold on to a reference to a filestream,
|
||||
// even if we're always just reading from in.
|
||||
// We still have to CLOSE the file handle afterwards!
|
||||
static std::ifstream ifs;
|
||||
static std::istringstream iss;
|
||||
|
||||
// Indicates whether EOF has been reached
|
||||
static bool reachedEof;
|
||||
// Indicates whether this class has been initialized
|
||||
static bool initialized;
|
||||
|
||||
// Are we reading ciphertext or regular text?
|
||||
static bool isReadingCiphertext;
|
||||
|
||||
// How many blocks have been read in total
|
||||
static std::size_t nBlocksRead;
|
||||
|
||||
// All read blocks, that haven't been given out yet
|
||||
static std::queue<Block> blocks;
|
||||
|
||||
// No instanciation! >:(
|
||||
DataIngestionLayer();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,61 +0,0 @@
|
||||
#ifndef GCRYPTCLI_DATAOUTPUTLAYER_H
|
||||
#define GCRYPTCLI_DATAOUTPUTLAYER_H
|
||||
|
||||
#include <iosfwd>
|
||||
#include <queue>
|
||||
#include <GCrypt/Block.h>
|
||||
#include "Configuration.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
namespace IO {
|
||||
|
||||
// This class is used to read in data.
|
||||
class DataOutputLayer {
|
||||
public:
|
||||
//! Will initialize the output
|
||||
static void Init();
|
||||
|
||||
//! Will destruct the output layer (like, closing file handles)
|
||||
static void Destruct();
|
||||
|
||||
//! Will queue a block for writing
|
||||
static void Enqueue(const Block& block);
|
||||
|
||||
//! Will attempt to write the next block
|
||||
static void WriteBlock();
|
||||
|
||||
//! Indicates that no more blocks will be enqueued
|
||||
static void ReachedEOF();
|
||||
|
||||
//! Returns true, if all blocks have been written, and an EOF signal as been received
|
||||
static bool IsFinished();
|
||||
|
||||
private:
|
||||
//! If we are finished, and are outputting to stdout,
|
||||
//! and the user didn't specifically opt out, print a newline
|
||||
static void AddTrailingLinebreakIfRequired();
|
||||
|
||||
static std::ostream* out;
|
||||
|
||||
// We have to hold on to a reference to a filestream,
|
||||
// even if we're always just reading from in.
|
||||
// We still have to CLOSE the file handle afterwards!
|
||||
static std::ofstream ofs;
|
||||
|
||||
// Indicates whether EOF has been reached
|
||||
static bool reachedEof;
|
||||
|
||||
// Indicates whether this class has been initialized
|
||||
static bool initialized;
|
||||
|
||||
// All blocks, that haven't been written yet
|
||||
static std::queue<Block> blocks;
|
||||
|
||||
//! No instanciation >:(
|
||||
DataOutputLayer() {};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,30 +0,0 @@
|
||||
#ifndef GCRYPTCLI_KEYMANAGER_H
|
||||
#define GCRYPTCLI_KEYMANAGER_H
|
||||
|
||||
#include <GCrypt/Key.h>
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
// This class has the task to prepare and supply the encryption key.
|
||||
class KeyManager {
|
||||
public:
|
||||
//! Will prepare the key. Be it from cli, a file, or, random, or whatever.
|
||||
static void PrepareKey();
|
||||
|
||||
//! Will return the key, if prepared.
|
||||
static const Key& GetKey();
|
||||
|
||||
private:
|
||||
//! Will ask for a password on stdin,
|
||||
//! hiding the input.
|
||||
static std::string PasswordPrompt();
|
||||
|
||||
//! The encryption key
|
||||
static Key key;
|
||||
|
||||
// No instanciation! >:(
|
||||
KeyManager() {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,18 +0,0 @@
|
||||
#ifndef GCRYPTCLI_MODULE_DECRYPTION_H
|
||||
#define GCRYPTCLI_MODULE_DECRYPTION_H
|
||||
|
||||
namespace Module {
|
||||
//! This module will decrypt supplied input
|
||||
class Decryption {
|
||||
public:
|
||||
//! Will run the module
|
||||
static void Run();
|
||||
|
||||
private:
|
||||
// No instanciation! >:(
|
||||
Decryption() {};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,18 +0,0 @@
|
||||
#ifndef GCRYPTCLI_MODULE_ENCRYPTION_H
|
||||
#define GCRYPTCLI_MODULE_ENCRYPTION_H
|
||||
|
||||
namespace Module {
|
||||
//! This module will encrypt supplied input
|
||||
class Encryption {
|
||||
public:
|
||||
//! Will run the module
|
||||
static void Run();
|
||||
|
||||
private:
|
||||
// No instanciation! >:(
|
||||
Encryption() {};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,19 +0,0 @@
|
||||
#ifndef GCRYPTCLI_MODULE_GENERATEKEY_H
|
||||
#define GCRYPTCLI_MODULE_GENERATEKEY_H
|
||||
|
||||
namespace Module {
|
||||
// This module just generates a key, and outputs it.
|
||||
// Can be used to create a keyfiles.
|
||||
class GenerateKey {
|
||||
public:
|
||||
//! Will write the key to a file
|
||||
static void Run();
|
||||
|
||||
private:
|
||||
// No instanciation! >:(
|
||||
GenerateKey() {};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,18 +0,0 @@
|
||||
#ifndef GCRYPTCLI_MODULE_HASHING_H
|
||||
#define GCRYPTCLI_MODULE_HASHING_H
|
||||
|
||||
namespace Module {
|
||||
//! This module will hash supplied input
|
||||
class Hashing {
|
||||
public:
|
||||
//! Will run the module
|
||||
static void Run();
|
||||
|
||||
private:
|
||||
// No instanciation! >:(
|
||||
Hashing() {};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,23 +0,0 @@
|
||||
#ifndef GCRYPTCLI_PROGRESSPRINTER_H
|
||||
#define GCRYPTCLI_PROGRESSPRINTER_H
|
||||
|
||||
#include <iostream>
|
||||
#include "CommandlineInterface.h"
|
||||
|
||||
// This class has the task to output progress to stderr, if requested
|
||||
class ProgressPrinter {
|
||||
public:
|
||||
//! Will print progress to stderr, if requested, and the interval matches
|
||||
static void PrintIfAppropriate(
|
||||
const std::string& message,
|
||||
const std::size_t current,
|
||||
const std::size_t target
|
||||
);
|
||||
|
||||
private:
|
||||
// No instanciation! >:(
|
||||
ProgressPrinter() {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,7 +0,0 @@
|
||||
#ifndef GCRYPTCLI_VERSION_H
|
||||
#define GCRYPTCLI_VERSION_H
|
||||
|
||||
#define GCRYPTCLI_VERSION 0.12512
|
||||
|
||||
#endif
|
||||
|
@ -1,890 +0,0 @@
|
||||
# GCrypt CLI
|
||||
Easy text and file encryption via the command line using GCrypt. Now supporting [*esoteric data formats*](#esoteric-data-formats)... :)
|
||||
Again, please only use this as an obfuscator or if the only other option would be no encryption at all.
|
||||
Do you want to quickly and securely encrypt stuff via the command line? Use openssl-cli with the aes cipher. It's a bit more wordy but much faster and more secure.
|
||||
|
||||
Still want to use GCrypt cli? Here ya go!
|
||||
Just clone this repository, navigate into this directory and compile it:
|
||||
|
||||
## How do i use this?
|
||||
### Prerequsities:
|
||||
Have these depencies installed:
|
||||
* git
|
||||
* make
|
||||
* cmake
|
||||
* build-essentials (c++ >= 17) (might work with 11, if you're lucky)
|
||||
|
||||
### How2compile
|
||||
1) Clone this repository.
|
||||
2) Download all submodules: `git submodule update --init --recursive`.
|
||||
3) Cd into /GCryptCLI: `cd GCryptCLI`.
|
||||
4) Create a build directory: `cmake -B build`.
|
||||
5) Cd into the build directory: `cd build`.
|
||||
6) Compile: `make`.
|
||||
The executable `gcrypt` should now lie in `build/`.
|
||||
|
||||
If you want to use this globally, you could move it to `/usr/bin/`, or some other location in your $PATH. ### Options and flags
|
||||
|
||||
### All arguments and flags:
|
||||
```
|
||||
CLI for the GCrypt cipher/obfuscator
|
||||
Copyright (c) 2022 Leon Etienne
|
||||
GCryptLib v0.236
|
||||
GCryptCLI v0.12511
|
||||
THIS IS EXPERIMENTAL SOFTWARE AND MUST BE CONSIDERED INSECURE. DO NOT USE THIS TO ENCRYPT SENSITIVE DATA! READ THE README FILES ACCESSIBLE AT "https://gitea.leonetienne.de/leonetienne/GCrypt"
|
||||
|
||||
==== AVAILABLE PARAMETERS ====
|
||||
|
||||
--iobase-bytes VOID incompatibilities=[--iobase-2, --iobase-8, --iobase-10, --iobase-16, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and output ciphertexts as raw bytes.
|
||||
|
||||
--iobase-16 VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base16 (hex)
|
||||
|
||||
--progress-interval INT default=['1000'] Print digestion progress reports every these many data blocks.
|
||||
|
||||
--buffer-input VOID Will read the entire input before beginning any digestion.
|
||||
|
||||
--progress -p VOID Print digestion progress to stderr. May be advisable for large files, as the cipher is rather slow.
|
||||
|
||||
--cli-version -v VOID Will supply the version of GCryptCLI used.
|
||||
|
||||
--keyfile -kf STRING incompatibilities=[--key, --keyask, --hash] Read in the first {KEYSIZE}(=512) bits of this file and use that as an encryption key. WARNING: Arguments may be logged by the system!
|
||||
|
||||
--iobase-2 VOID incompatibilities=[--iobase-bytes, --iobase-8, --iobase-10, --iobase-16, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base2
|
||||
|
||||
--iobase-10 VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-16, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base10
|
||||
|
||||
--buffer-output VOID Will digest the entire data before initiating any output.
|
||||
|
||||
--lib-version VOID Will supply the version of GCryptLib used.
|
||||
|
||||
--iobase-ugh VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-10, --iobase-16, --iobase-64, --iobase-uwu] Interpret and format ciphertexts in base ugh
|
||||
|
||||
--infile -if STRING incompatibilities=[--intext] Encrypt this file.
|
||||
|
||||
--iobase-uwu VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-10, --iobase-16, --iobase-64, --iobase-ugh] Interpret and format ciphertexts in base uwu
|
||||
|
||||
--iobase-64 VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-10, --iobase-16, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base64
|
||||
|
||||
--iobase-8 VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-10, --iobase-16, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base8
|
||||
|
||||
--encrypt -e VOID incompatibilities=[--decrypt, --hash] Use the encryption module.
|
||||
|
||||
--generate-key VOID incompatibilities=[--encrypt, --decrypt, --hash] Use the key generation module. Will generate a random key based on hardware events, output it, and exit.
|
||||
|
||||
--ofile -o STRING incompatibilities=[--ostdout, --hash] Write output in this file.
|
||||
|
||||
--key -k STRING incompatibilities=[--keyfile, --keyask, --hash] Use this value as a password to extrapolate the encryption key. WARNING: Arguments may be logged by the system!
|
||||
|
||||
--keyask -ka VOID incompatibilities=[--key, --keyfile, --hash] Read the encryption key from stdin.
|
||||
|
||||
--no-newline VOID Don't postfix stdout output with a newline
|
||||
|
||||
--decrypt -d VOID incompatibilities=[--encrypt, --hash, --generate-key] Use decryption module.
|
||||
|
||||
--hash -h VOID incompatibilities=[--encrypt, --decrypt, --generate-key] Use the GHash hash module to calculate a hashsum.
|
||||
|
||||
--intext -it STRING incompatibilities=[--infile] Encrypt this string.
|
||||
```
|
||||
|
||||
### Examples
|
||||
Please note that commonly used arguments are supplied in their short form (`-e` in place of `--encrypt`).
|
||||
|
||||
#### I want to encrypt text!
|
||||
```sh
|
||||
$ gcrypt -e --keyask --intext "hello, world!"
|
||||
efbebc429c8370bf84f00b0d8ccbaf7858b3b87d71ff58cb1cfefa8fb0c68094c0865565873aa8a5254ede59be46e81a4d4917e679b18cb290dbd6669cb6207a
|
||||
```
|
||||
|
||||
#### Now decrypt it
|
||||
```sh
|
||||
$ gcrypt -d --keyask --intext "efbebc429c8370bf84f00b0d8ccbaf7858b3b87d71ff58cb1cfefa8fb0c68094c0865565873aa8a5254ede59be46e81a4d4917e679b18cb290dbd6669cb6207a"
|
||||
hello, world!
|
||||
```
|
||||
|
||||
#### What about not using hex?
|
||||
> :warning: Custom bases are super imperformant. Please only use them for text-based input...
|
||||
> The larger the base, the exponentially longer it takes to recode.
|
||||
|
||||
```sh
|
||||
$ gcrypt -e --keyask --intext "hello, world!" --iobase-2
|
||||
111001001011100000011111000100010100110011100110000100100101001001110001001000101011110000000011011100001010111010001000110111110110011011100000001100110001001000100111011000101010010001011011111011001000011111100100101001011110011101110001010011000101011001111010000001001100101110000101101101101001110100100001101010111101010000100111101110000110011101100101101011000011101001000011010010011001111010001001101000101001100101010000100010111101101100010000000001001110010001001011001001011011010111001101000100
|
||||
|
||||
$ gcrypt -e --keyask --intext "hello, world!" --iobase-8
|
||||
71134037042463460445116110536003341272106766334014611047305221337310374451363561230531720114560555516441527520475606354553035103223172115051452042755420011621131133271504
|
||||
|
||||
$ gcrypt -e --keyask --intext "hello, world!" --iobase-10
|
||||
2994749439449970047518881970731547473115480925772565399786126223459744370490386223437520234266936877059618216185983047971748564015130703048737306773910340
|
||||
|
||||
$ gcrypt -e --keyask --intext "hello, world!" --iobase-64
|
||||
Co/WjpV5nPrCaz0QMdrXAXzzOH5HODRsBNL22KZowmGMcTLwfmsQpzt7Ik+ViR5vOhUXowFQeR5x2vbcj1X5ae
|
||||
```
|
||||
I won't be pasting in stdout for every example. It would become too cluttered.
|
||||
|
||||
#### Passing the key as an argument
|
||||
```sh
|
||||
$ gcrypt -e --key "secretpassword" --intext "hello, world!"
|
||||
```
|
||||
> :warning: Some operating systems will log cli arguments! THIS WOULD BE THE ENTIRE KEY!
|
||||
|
||||
#### Using keyfiles
|
||||
```sh
|
||||
$ gcrypt -e --keyfile "dog.jpg" --intext "hello, world!"
|
||||
```
|
||||
> :warning: Some operating systems will log cli arguments! One might find your keyfile!
|
||||
|
||||
#### Creating keyfiles
|
||||
```sh
|
||||
$ gcrypt --generate-key --ofile "my-keyfile.bin"
|
||||
```
|
||||
This will generate a random 512-bit keyfile from hardware events and other random sources, if available.
|
||||
To see how this randomness gets sourced, see [std::random_device](https://en.cppreference.com/w/cpp/numeric/random/random_device).
|
||||
|
||||
#### Encrypting files
|
||||
```sh
|
||||
$ gcrypt -e --keyask --infile "cat.jpg" --ofile "cat.jpg.crypt"
|
||||
```
|
||||
File `cat.jpg.crypt` will be created.
|
||||
|
||||
#### Decrypting files
|
||||
```sh
|
||||
$ gcrypt -d --keyask --infile "cat.jpg.crypt" --ofile "decrypted_cat.jpg"
|
||||
```
|
||||
File `decrypted_cat.jpg` will be created. You can now open it again. Its contents match `cat.jpg`.
|
||||
> :warning: Since this is a block cipher, decrypted files may be tailpadded with a few nullbytes.
|
||||
|
||||
#### Encrypting large files takes time. How's the progress?
|
||||
```sh
|
||||
$ gcrypt -e --keyask --infile "cat.jpg" --buffer-input --progress
|
||||
```
|
||||
Something along the lines of `Encrypting... (Block 200 / 1148 - 17.4216%)` will be regularly, but not too often, printed to stderr.
|
||||
Obviously, to print progress, we have to know the size of the input. Hence, it has to be buffered.
|
||||
|
||||
#### Any cipher can also compute hashsums
|
||||
```sh
|
||||
$ gcrypt -h --intext "hello, world!"
|
||||
a96f42c9d97e46b9e1ed7de5182770170d4ef9b7b8264f3fbd89b38dc60c1fe06232653f5856013307fc020fb1d35f2bea26bc0f373c5ac35a722c6b03d8254d
|
||||
|
||||
$ gcrypt -h --infile "cat.jpg"
|
||||
fe6bdfb6ec39771c4fdcdc40e52397bcd67fbfef0ad5a15ebbd8b9e4c2a815848b3984eda5ef6f727e9e420c23500c90c42ab80ac5659048be8969357741e3e5
|
||||
```
|
||||
The hashsum will always be of size BLOCK_SIZE. That is 512 bits.
|
||||
|
||||
#### What version am i running?
|
||||
Depending on whether you want to know the GCryptLib version or the CLI's version,
|
||||
use either `--cli-version` or `--lib-version`.
|
||||
It will print out a floating point number.
|
||||
You can see both in the `--help`-page.
|
||||
|
||||
#### Streaming the output of file en/decryption.
|
||||
Easily! If you do not supply any output or input, stdout and stdin will be used instead!
|
||||
```sh
|
||||
# mpv is a media player, as an example
|
||||
$ gcrypt -d --key "123" --infile "music.mp3.crypt" | mpv -
|
||||
```
|
||||
|
||||
#### Don't want to stream input and output?
|
||||
By default, gcrypt will read a block, digest it, and output the result immediately.
|
||||
Sometimes you don't want that. Use these flags, respectively:
|
||||
```
|
||||
--buffer-input # Reads all input to memory before beginning to digest it
|
||||
--buffer-output # Digests all input before beginning to write any
|
||||
```
|
||||
|
||||
## Esoteric data formats
|
||||
#### Base *UwU*
|
||||
```sh
|
||||
$ gcrypt -e --keyask --intext "hello, world!" --iobase-uwu
|
||||
:) sewnpaiii tastieee uhh?! nappies cutewr twe best cutieee :O tastieee senpaiiiw favowite toesy-woesies ^.^ :3 best chomp whiffle uwu Awww sewnpaiii comfy-womfy :p keewl Awww youuu nyeko :O tasties hiiiii heeeey (*^_^*) youuu toot uhh..? smush (*^_^*) *bites-lip* whiffle haaaay nyah! comfy-womfy :) cutsie Owww haaaay snaffle haaaai haaaai nyeko *sweats* :) uhh..? boop toot *bites-lip* <3 whiiiich whiffskaws ^.^ twe whiffskaws hiiiii *sweats* Owww dewicious i tasties :P awe hewwo boop rawr uwu dewicious eughh twe cutsie xD
|
||||
```
|
||||
|
||||
#### Base **UGH!**
|
||||
```sh
|
||||
$ gcrypt -e --keyask --intext "hello, world!" --iobase-ugh
|
||||
Grr... Wha-? Aah! Aah! Uh-huh... Aah! Grr... Aah! Aah! Uh-huh... Ah... Ugh Grr... Ugh Pft! Nu-uh... Gah! Bah! Huh...? Ah... Uh-huh... Wha-? Pft! Nu-uh... Ugh Wha-? Psh! Agh! Ah... Aah! Nu-uh... Psh! Pft! Nu-uh... Psh! Shh! Gah! Ah... Pft! Gah! Shh! Bah! Gah! Uh-huh... Gah! Duh! Aah! Uh-huh... Er- Nu-uh... Gah! Wha-? Pft! Er- Shh! Ah... Huh...? Er- Wha-? Uh-huh... Ah... Shh! Ugh Bah! Wha-? Uaah! Ah... Nu-uh... Uh-huh... Ugh Pft! Pft! Gah! Shh! Shh! Wha-? Bah! Ugh Grr... Aah! Pft! Nu-uh... Ah... Aah! Agh! Er- Psh! Uaah! Nu-uh... Ugh Wha-? Uh-huh... Shh! Pft! Aah! Agh! Grr... Agh! Agh! Grr... Pft! Wha-? Wha-? Uh-huh... Aah! Ugh Aah! Pft! Gah! Bah! Huh...? Ugh Bah! Uaah! Gah! Bah! Duh! Duh! Uh-huh... Grr... Ah... Grr... Ugh Ah... Pft!
|
||||
```
|
||||
|
||||
Yes, you can send these... *adventorous* texsts to your friends, and they can actually decipher them
|
||||
back to the original message :). Almost going a bit into the steganography territory here, hehe.
|
||||
|
||||
These weird number bases don't impact security at all. This is because they are just that.
|
||||
Number bases, to represent a bunch of bytes, that is our ciphertext.
|
||||
|
||||
These just bring a bit more fun into the big world of cryptography :).
|
||||
|
||||
## LICENSE
|
||||
```
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
```
|
@ -1,213 +0,0 @@
|
||||
#include "CommandlineInterface.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <GCrypt/Version.h>
|
||||
#include <GCrypt/Block.h>
|
||||
#include "Version.h"
|
||||
|
||||
using namespace Hazelnp;
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
void CommandlineInterface::Init(int argc, const char* const* argv) {
|
||||
/* General information */
|
||||
std::stringstream ss;
|
||||
ss << "CLI for the GCrypt cipher/obfuscator" << std::endl
|
||||
<< "Copyright (c) 2022 Leon Etienne" << std::endl
|
||||
<< "GCryptLib v" << GCRYPT_VERSION << std::endl
|
||||
<< "GCryptCLI v" << GCRYPTCLI_VERSION << std::endl
|
||||
<< "THIS IS EXPERIMENTAL SOFTWARE AND MUST BE CONSIDERED INSECURE. DO NOT USE THIS TO ENCRYPT SENSITIVE DATA! READ THE README FILES ACCESSIBLE AT \"https://gitea.leonetienne.de/leonetienne/GCrypt\"";
|
||||
nupp.SetBriefDescription(ss.str());
|
||||
ss.str("");
|
||||
nupp.SetCatchHelp("true");
|
||||
nupp.SetCrashOnFail("true");
|
||||
|
||||
/* Builtin documentation */
|
||||
nupp.RegisterDescription("--encrypt", "Use the encryption module.");
|
||||
nupp.RegisterConstraint("--encrypt", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {"--decrypt", "--hash" }));
|
||||
nupp.RegisterAbbreviation("-e", "--encrypt");
|
||||
|
||||
nupp.RegisterDescription("--decrypt", "Use decryption module.");
|
||||
nupp.RegisterConstraint("--decrypt", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--encrypt", "--hash", "--generate-key" }));
|
||||
nupp.RegisterAbbreviation("-d", "--decrypt");
|
||||
|
||||
nupp.RegisterDescription("--hash", "Use the GHash hash module to calculate a hashsum.");
|
||||
nupp.RegisterConstraint("--hash", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--encrypt", "--decrypt", "--generate-key" }));
|
||||
nupp.RegisterAbbreviation("-h", "--hash");
|
||||
|
||||
nupp.RegisterDescription("--generate-key", "Use the key generation module. Will generate a random key based on hardware events, output it, and exit.");
|
||||
nupp.RegisterConstraint("--generate-key", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--encrypt", "--decrypt", "--hash" }));
|
||||
|
||||
nupp.RegisterDescription("--intext", "Encrypt this string.");
|
||||
nupp.RegisterConstraint("--intext", ParamConstraint(true, DATA_TYPE::STRING, {}, false, { "--infile" }));
|
||||
nupp.RegisterAbbreviation("-it", "--intext");
|
||||
|
||||
nupp.RegisterDescription("--infile", "Encrypt this file.");
|
||||
nupp.RegisterConstraint("--infile", ParamConstraint(true, DATA_TYPE::STRING, {}, false, { "--intext" }));
|
||||
nupp.RegisterAbbreviation("-if", "--infile");
|
||||
|
||||
nupp.RegisterDescription("--ofile", "Write output in this file.");
|
||||
nupp.RegisterConstraint("--ofile", ParamConstraint(true, DATA_TYPE::STRING, {}, false, { "--ostdout", "--hash" }));
|
||||
nupp.RegisterAbbreviation("-of", "--ofile");
|
||||
nupp.RegisterAbbreviation("-o", "--ofile");
|
||||
|
||||
nupp.RegisterDescription("--key", "Use this value as a password to extrapolate the encryption key. WARNING: Arguments may be logged by the system!");
|
||||
nupp.RegisterConstraint("--key", ParamConstraint(true, DATA_TYPE::STRING, {}, false, { "--keyfile", "--keyask", "--hash" }));
|
||||
nupp.RegisterAbbreviation("-k", "--key");
|
||||
|
||||
ss << "Read in the first {KEYSIZE}(=" << Block::BLOCK_SIZE_BITS << ") bits of this file and use that as an encryption key. WARNING: Arguments may be logged by the system!";
|
||||
nupp.RegisterDescription("--keyfile", ss.str());
|
||||
ss.str("");
|
||||
nupp.RegisterConstraint("--keyfile", ParamConstraint(true, DATA_TYPE::STRING, {}, false, { "--key", "--keyask", "--hash" }));
|
||||
nupp.RegisterAbbreviation("-kf", "--keyfile");
|
||||
|
||||
nupp.RegisterDescription("--keyask", "Read the encryption key from stdin.");
|
||||
nupp.RegisterConstraint("--keyask", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--key", "--keyfile", "--hash" }));
|
||||
nupp.RegisterAbbreviation("-ka", "--keyask");
|
||||
|
||||
nupp.RegisterDescription("--progress", "Print digestion progress to stderr. May be advisable for large files, as the cipher is rather slow.");
|
||||
nupp.RegisterConstraint("--progress", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
|
||||
nupp.RegisterAbbreviation("-p", "--progress");
|
||||
|
||||
nupp.RegisterDescription("--progress-interval", "Print digestion progress reports every these many data blocks.");
|
||||
nupp.RegisterConstraint("--progress-interval", ParamConstraint(true, DATA_TYPE::INT, { "1000" }, true, {}));
|
||||
|
||||
nupp.RegisterDescription("--iobase-bytes", "Interpret and output ciphertexts as raw bytes.");
|
||||
nupp.RegisterConstraint("--iobase-bytes", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-2", "--iobase-8", "--iobase-10", "--iobase-16", "--iobase-64", "--iobase-uwu", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-2", "Interpret and format ciphertexts in base2");
|
||||
nupp.RegisterConstraint("--iobase-2", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-8", "--iobase-10", "--iobase-16", "--iobase-64", "--iobase-uwu", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-8", "Interpret and format ciphertexts in base8");
|
||||
nupp.RegisterConstraint("--iobase-8", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-2", "--iobase-10", "--iobase-16", "--iobase-64", "--iobase-uwu", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-10", "Interpret and format ciphertexts in base10");
|
||||
nupp.RegisterConstraint("--iobase-10", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-2", "--iobase-8", "--iobase-16", "--iobase-64", "--iobase-uwu", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-16", "Interpret and format ciphertexts in base16 (hex)");
|
||||
nupp.RegisterConstraint("--iobase-16", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-2", "--iobase-8", "--iobase-64", "--iobase-uwu", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-64", "Interpret and format ciphertexts in base64");
|
||||
nupp.RegisterConstraint("--iobase-64", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-2", "--iobase-8", "--iobase-10", "--iobase-16", "--iobase-uwu", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-uwu", "Interpret and format ciphertexts in base uwu");
|
||||
nupp.RegisterConstraint("--iobase-uwu", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-2", "--iobase-8", "--iobase-10", "--iobase-16", "--iobase-64", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-ugh", "Interpret and format ciphertexts in base ugh");
|
||||
nupp.RegisterConstraint("--iobase-ugh", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-2", "--iobase-8", "--iobase-10", "--iobase-16", "--iobase-64", "--iobase-uwu" }));
|
||||
|
||||
nupp.RegisterDescription("--lib-version", "Will supply the version of GCryptLib used.");
|
||||
nupp.RegisterConstraint("--lib-version", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
|
||||
|
||||
nupp.RegisterDescription("--cli-version", "Will supply the version of GCryptCLI used.");
|
||||
nupp.RegisterConstraint("--cli-version", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
|
||||
nupp.RegisterAbbreviation("-v", "--cli-version");
|
||||
|
||||
nupp.RegisterDescription("--buffer-input", "Will read the entire input before beginning any digestion.");
|
||||
nupp.RegisterConstraint("--buffer-input", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
|
||||
|
||||
nupp.RegisterDescription("--buffer-output", "Will digest the entire data before initiating any output.");
|
||||
nupp.RegisterConstraint("--buffer-output", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
|
||||
|
||||
nupp.RegisterDescription("--no-newline", "Don't postfix stdout output with a newline");
|
||||
nupp.RegisterConstraint("--no-newline", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
|
||||
|
||||
/* Now parse */
|
||||
nupp.Parse(argc, argv);
|
||||
|
||||
CatchVersionQueries();
|
||||
SpecialCompatibilityChecking();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Hazelnp::CmdArgsInterface& CommandlineInterface::Get() {
|
||||
return nupp;
|
||||
}
|
||||
|
||||
void CommandlineInterface::SpecialCompatibilityChecking() {
|
||||
|
||||
// Active module
|
||||
// Do we have EITHER --encrypt or --decrypt or --hash?
|
||||
if (
|
||||
(!nupp.HasParam("--generate-key")) &&
|
||||
(!nupp.HasParam("--hash")) &&
|
||||
(!nupp.HasParam("--encrypt")) &&
|
||||
(!nupp.HasParam("--decrypt"))
|
||||
) {
|
||||
CrashWithMsg("No module supplied! Please supply either --encrypt, --decrypt, --hash, or --generate-key!");
|
||||
}
|
||||
|
||||
// Encryption key
|
||||
// Do we have EITHER --hash (no key required), --generate-key (no key required), --key, --keyask or --keyfile given?
|
||||
if (
|
||||
(!nupp.HasParam("--hash")) &&
|
||||
(!nupp.HasParam("--generate-key")) &&
|
||||
(!nupp.HasParam("--key")) &&
|
||||
(!nupp.HasParam("--keyfile")) &&
|
||||
(!nupp.HasParam("--keyask"))
|
||||
) {
|
||||
CrashWithMsg("No encryption key supplied! Please supply either --key, --keyfile, or --keyask!");
|
||||
}
|
||||
|
||||
// Check that, if supplied, filename strings are not empty.
|
||||
if (
|
||||
(nupp.HasParam("--ofile")) &&
|
||||
(nupp["--ofile"].GetString().length() == 0)
|
||||
) {
|
||||
CrashWithMsg("Length of --ofile is zero! That can't be a valid path!");
|
||||
}
|
||||
|
||||
if (
|
||||
(nupp.HasParam("--ifile")) &&
|
||||
(nupp["--ifile"].GetString().length() == 0)
|
||||
) {
|
||||
CrashWithMsg("Length of --ifile is zero! That can't be a valid path!");
|
||||
}
|
||||
|
||||
if (
|
||||
(nupp.HasParam("--keyfile")) &&
|
||||
(nupp["--keyfile"].GetString().length() == 0)
|
||||
) {
|
||||
CrashWithMsg("Length of --keyfile is zero! That can't be a valid path!");
|
||||
}
|
||||
|
||||
if (
|
||||
(nupp.HasParam("--progress")) &&
|
||||
(!nupp.HasParam("--buffer-input"))
|
||||
|
||||
) {
|
||||
CrashWithMsg("--progress requires --buffer-input to work!");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void CommandlineInterface::CrashWithMsg(const std::string& msg) {
|
||||
std::cerr
|
||||
<< nupp.GetBriefDescription()
|
||||
<< std::endl
|
||||
<< "Fatal error! Unable to continue! More information:" << std::endl
|
||||
<< msg << std::endl;
|
||||
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void CommandlineInterface::CatchVersionQueries() {
|
||||
if (
|
||||
(nupp.HasParam("--version")) ||
|
||||
(nupp.HasParam("--cli-version"))
|
||||
) {
|
||||
std::cout << GCRYPTCLI_VERSION << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
else if (nupp.HasParam("--lib-version"))
|
||||
{
|
||||
std::cout << GCRYPT_VERSION << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CmdArgsInterface CommandlineInterface::nupp;
|
||||
|
@ -1,186 +0,0 @@
|
||||
#include "Configuration.h"
|
||||
#include "CommandlineInterface.h"
|
||||
|
||||
void Configuration::Parse() {
|
||||
DecideModule();
|
||||
DecideInputFrom();
|
||||
DecideOutputTo();
|
||||
DecideCiphertextFormat();
|
||||
MapCiphertextFormatToIOBases();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Configuration::DecideModule() {
|
||||
if (CommandlineInterface::Get().HasParam("--encrypt")) {
|
||||
activeModule = MODULE::ENCRYPTION;
|
||||
return;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--decrypt")) {
|
||||
activeModule = MODULE::DECRYPTION;
|
||||
return;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--hash")) {
|
||||
activeModule = MODULE::HASH;
|
||||
return;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--generate-key")) {
|
||||
activeModule = MODULE::GENERATE_KEY;
|
||||
return;
|
||||
}
|
||||
|
||||
throw std::runtime_error("No module option found. Is the CLI parser configuration correct?.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Configuration::DecideInputFrom() {
|
||||
|
||||
if (CommandlineInterface::Get().HasParam("--intext")) {
|
||||
inputFrom = INPUT_FROM::PARAMETER;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--infile")) {
|
||||
inputFrom = INPUT_FROM::FILE;
|
||||
inputFilename = CommandlineInterface::Get()["--infile"].GetString();
|
||||
}
|
||||
else {
|
||||
inputFrom = INPUT_FROM::STDIN;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Configuration::DecideOutputTo() {
|
||||
|
||||
if (CommandlineInterface::Get().HasParam("--ofile")) {
|
||||
outputTo = OUTPUT_TO::FILE;
|
||||
outputFilename = CommandlineInterface::Get()["--ofile"].GetString();
|
||||
}
|
||||
else {
|
||||
outputTo = OUTPUT_TO::STDOUT;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Configuration::DecideCiphertextFormat() {
|
||||
|
||||
// Do we have any iobase explicitly specified?
|
||||
if (CommandlineInterface::Get().HasParam("--iobase-bytes")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_BYTES;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-2")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_2;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-8")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_8;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-10")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_10;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-16")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_16;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-64")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_64;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-uwu")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_UWU;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-ugh")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_UGH;
|
||||
}
|
||||
|
||||
// So we have no iobase explicitly specified.. Let's default..
|
||||
|
||||
// If we are encrypting,
|
||||
else if (activeModule == MODULE::ENCRYPTION) {
|
||||
// and input comes from a parameter,
|
||||
// and output goes to stdout,
|
||||
// let's assume base-16.
|
||||
if (
|
||||
(inputFrom == INPUT_FROM::PARAMETER) &&
|
||||
(outputTo == OUTPUT_TO::STDOUT)
|
||||
) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_16;
|
||||
}
|
||||
|
||||
// Any other case whilst encrypting, we'll assume base-bytes.
|
||||
else {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_BYTES;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Else, if we are hashing,
|
||||
else if (activeModule == MODULE::HASH) {
|
||||
// output is always defaults to base 16
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_16;
|
||||
}
|
||||
|
||||
// Else, if we are decrypting,
|
||||
else if (activeModule == MODULE::DECRYPTION) {
|
||||
// and input comes from a parameter, we'll assume base-16.
|
||||
if (inputFrom == INPUT_FROM::PARAMETER) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_16;
|
||||
}
|
||||
// Any other case whilst decrypting, we'll assume base-bytes.
|
||||
else {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
// Else, if we are generating a key,
|
||||
else if (activeModule == MODULE::GENERATE_KEY) {
|
||||
// and we're outputting to stdout, we'll use base-16.
|
||||
if (outputTo == OUTPUT_TO::STDOUT) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_16;
|
||||
}
|
||||
// else, we're outputting to a file, use base-bytes.
|
||||
else {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: Bytes
|
||||
else {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_BYTES;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Configuration::MapCiphertextFormatToIOBases() {
|
||||
|
||||
// Now, map the ciphertextFormat to either formatIn or formatOut.
|
||||
switch (activeModule) {
|
||||
// For encryption, keygen, and hashing:
|
||||
// input is bytes and output is ciphertext
|
||||
case MODULE::ENCRYPTION:
|
||||
case MODULE::HASH:
|
||||
case MODULE::GENERATE_KEY:
|
||||
formatIn = IOBASE_FORMAT::BASE_BYTES;
|
||||
formatOut = ciphertextFormat;
|
||||
break;
|
||||
|
||||
// For decryption:
|
||||
// input is ciphertext and output is bytes
|
||||
case MODULE::DECRYPTION:
|
||||
formatIn = ciphertextFormat;
|
||||
formatOut = IOBASE_FORMAT::BASE_BYTES;
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string Configuration::inputFilename;
|
||||
std::string Configuration::outputFilename;
|
||||
Configuration::MODULE Configuration::activeModule;
|
||||
Configuration::IOBASE_FORMAT Configuration::formatIn;
|
||||
Configuration::IOBASE_FORMAT Configuration::formatOut;
|
||||
Configuration::IOBASE_FORMAT Configuration::ciphertextFormat;
|
||||
Configuration::INPUT_FROM Configuration::inputFrom;
|
||||
Configuration::OUTPUT_TO Configuration::outputTo;
|
||||
|
@ -1,299 +0,0 @@
|
||||
#include "DataFormatter.h"
|
||||
#include "Bases.h"
|
||||
#include <GeneralUtility/BaseConversion.h>
|
||||
#include <StringTools/StringTools.h>
|
||||
#include <GCrypt/Util.h>
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
using namespace Leonetienne::StringTools;
|
||||
using namespace Leonetienne::GeneralUtility;
|
||||
|
||||
std::string DataFormatter::FormatBlock(
|
||||
const Block& block,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
) {
|
||||
switch (base) {
|
||||
case Configuration::IOBASE_FORMAT::BASE_BYTES:
|
||||
return block.ToByteString();
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_2:
|
||||
return block.ToBinaryString();
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_8:
|
||||
return Bin2CustomBase(
|
||||
block.ToBinaryString(),
|
||||
BASE_8,
|
||||
blockLengthByBase[base]
|
||||
);
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_10:
|
||||
return Bin2CustomBase(
|
||||
block.ToBinaryString(),
|
||||
BASE_10,
|
||||
blockLengthByBase[base]
|
||||
);
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_16:
|
||||
return block.ToHexString();
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_64:
|
||||
return Bin2CustomBase(
|
||||
block.ToBinaryString(),
|
||||
BASE_64,
|
||||
blockLengthByBase[base]
|
||||
);
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_UWU:
|
||||
return Bin2CustomBase(
|
||||
block.ToBinaryString(),
|
||||
BASE_UWU,
|
||||
blockLengthByBase[base],
|
||||
" "
|
||||
);
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_UGH:
|
||||
return Bin2CustomBase(
|
||||
block.ToBinaryString(),
|
||||
BASE_UGH,
|
||||
blockLengthByBase[base],
|
||||
" "
|
||||
);
|
||||
|
||||
default:
|
||||
throw std::invalid_argument("FormatBlock(): Iobase not found! Oh no. Anyway.");
|
||||
}
|
||||
}
|
||||
|
||||
std::string DataFormatter::FormatBlocks(
|
||||
const std::vector<Block>& blocks,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
) {
|
||||
std::stringstream ss;
|
||||
|
||||
std::size_t i = 0;
|
||||
for (const Block& block : blocks) {
|
||||
ss << FormatBlock(block, base);
|
||||
|
||||
// If we are dealing with a multichar base, we must append a
|
||||
// seperator (space), but only if its not the last block.
|
||||
if (
|
||||
(base == Configuration::IOBASE_FORMAT::BASE_UWU) ||
|
||||
(base == Configuration::IOBASE_FORMAT::BASE_UGH)
|
||||
) {
|
||||
if (i++ != blocks.size()) {
|
||||
ss << " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
Block DataFormatter::DecodeFormat(
|
||||
const std::string& str,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
) {
|
||||
|
||||
Block b;
|
||||
|
||||
switch (base) {
|
||||
case Configuration::IOBASE_FORMAT::BASE_BYTES:
|
||||
b.FromByteString(str);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_2:
|
||||
b.FromBinaryString(str);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_8:
|
||||
b.FromBinaryString(
|
||||
CustomBase2Bin(
|
||||
str,
|
||||
BASE_8
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_10:
|
||||
b.FromBinaryString(
|
||||
CustomBase2Bin(
|
||||
str,
|
||||
BASE_10
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_16:
|
||||
b.FromHexString(str);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_64:
|
||||
b.FromBinaryString(
|
||||
CustomBase2Bin(
|
||||
str,
|
||||
BASE_64
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_UWU:
|
||||
b.FromBinaryString(
|
||||
CustomBase2Bin(
|
||||
str,
|
||||
BASE_UWU,
|
||||
" "
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_UGH:
|
||||
b.FromBinaryString(
|
||||
CustomBase2Bin(
|
||||
str,
|
||||
BASE_UGH,
|
||||
" "
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::invalid_argument("StringToBlock(): Iobase now found! Oh no. Anyway.");
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
std::vector<Block> DataFormatter::DecodeFormatMultiblock(
|
||||
const std::string& str,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
) {
|
||||
std::vector<Block> blocks;
|
||||
|
||||
// A block is this many digits wide, in encoding
|
||||
const std::size_t blockWidth = blockLengthByBase[base];
|
||||
|
||||
// How many blocks are we dealing with here?
|
||||
const std::size_t n_blocks = (str.length() / blockWidth) + 1;
|
||||
blocks.reserve(n_blocks);
|
||||
|
||||
// Iterate over the string, and parse all blocks
|
||||
// We now have to differentiate between single-char digit sets (like hex),
|
||||
// and multi-char digit sets (like uwu):
|
||||
switch (base) {
|
||||
case Configuration::IOBASE_FORMAT::BASE_BYTES:
|
||||
case Configuration::IOBASE_FORMAT::BASE_2:
|
||||
case Configuration::IOBASE_FORMAT::BASE_8:
|
||||
case Configuration::IOBASE_FORMAT::BASE_10:
|
||||
case Configuration::IOBASE_FORMAT::BASE_16:
|
||||
case Configuration::IOBASE_FORMAT::BASE_64:
|
||||
// Easy case: Each digit is exactly one char in size.
|
||||
// We can just calculate how many bytes we should read.
|
||||
for (std::size_t i = 0; i < str.length(); i += blockWidth) {
|
||||
|
||||
const std::string subs = str.substr(i, blockWidth);
|
||||
|
||||
Block newBlock = DecodeFormat(
|
||||
subs,
|
||||
base
|
||||
);
|
||||
|
||||
blocks.emplace_back(newBlock);
|
||||
}
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_UWU:
|
||||
case Configuration::IOBASE_FORMAT::BASE_UGH: {
|
||||
// Hard case: Each digit is n digits long. Digits may vary in length.
|
||||
// They are seperated by spaces.
|
||||
// We have to parse them...
|
||||
std::size_t digitsPassed = 0;
|
||||
std::size_t blockStart = 0;
|
||||
for (std::size_t i = 0; i < str.length(); i++) {
|
||||
|
||||
if (str[i] == ' ') {
|
||||
digitsPassed++;
|
||||
|
||||
if (digitsPassed == blockWidth) {
|
||||
const std::string subs = str.substr(
|
||||
blockStart,
|
||||
i - blockStart
|
||||
);
|
||||
|
||||
Block newBlock = DecodeFormat(
|
||||
subs,
|
||||
base
|
||||
);
|
||||
|
||||
blocks.emplace_back(newBlock);
|
||||
|
||||
digitsPassed = 0;
|
||||
blockStart = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Here should never be any digits left. A formatted block should ALWAYS be full length.
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::invalid_argument("DataFormatter::StringToBlocks() has been passed an unknown base! No switch-case matched!");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return blocks;
|
||||
}
|
||||
|
||||
std::string DataFormatter::Bin2CustomBase(
|
||||
const std::string& bin,
|
||||
const std::vector<std::string>& customSet,
|
||||
const std::size_t minLen,
|
||||
const std::string& seperator
|
||||
) {
|
||||
std::stringstream ss;
|
||||
|
||||
// Translate to custom set
|
||||
const std::vector<std::string> vec_base_custom =
|
||||
Leonetienne::GeneralUtility::BaseConversion::BaseX_2_Y<std::string, std::vector<std::string>>(
|
||||
bin,
|
||||
"01",
|
||||
customSet,
|
||||
minLen
|
||||
);
|
||||
|
||||
// Convert to string
|
||||
for (std::size_t i = 0; i < vec_base_custom.size(); i++) {
|
||||
ss << vec_base_custom[i];
|
||||
|
||||
if (i != vec_base_custom.size() - 1) {
|
||||
ss << seperator;
|
||||
}
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string DataFormatter::CustomBase2Bin(
|
||||
const std::string& in,
|
||||
const std::vector<std::string>& customSet,
|
||||
const std::string& seperator
|
||||
) {
|
||||
// Split input into symbols
|
||||
const std::vector<std::string> in_symbols = StringTools::Split(in, seperator);
|
||||
|
||||
// Translate to binary
|
||||
std::string binary =
|
||||
Leonetienne::GeneralUtility::BaseConversion::BaseX_2_Y<std::vector<std::string>, std::string>(
|
||||
in_symbols,
|
||||
customSet,
|
||||
std::string("01"),
|
||||
Block::BLOCK_SIZE_BITS
|
||||
);
|
||||
|
||||
if (binary.length() != Block::BLOCK_SIZE_BITS) {
|
||||
throw std::invalid_argument("DataFormatter::CustomBase2Bin() received input that doesn't translate to a bitstring of length 512!");
|
||||
}
|
||||
|
||||
return binary;
|
||||
}
|
||||
|
@ -1,367 +0,0 @@
|
||||
#include "DataIngestionLayer.h"
|
||||
#include "CommandlineInterface.h"
|
||||
#include "DataFormatter.h"
|
||||
#include "Bases.h"
|
||||
#include <StringTools/StringTools.h>
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
using namespace IO;
|
||||
using namespace Leonetienne::StringTools;
|
||||
|
||||
void DataIngestionLayer::Init() {
|
||||
|
||||
// Set our istream
|
||||
switch (Configuration::inputFrom) {
|
||||
|
||||
// Are we reading from stdin?
|
||||
case Configuration::INPUT_FROM::STDIN:
|
||||
|
||||
// Redirect our istream to stdin
|
||||
in = &std::cin;
|
||||
break;
|
||||
|
||||
// Are we reading from a file?
|
||||
case Configuration::INPUT_FROM::FILE:
|
||||
|
||||
// Open the file
|
||||
ifs.open(
|
||||
Configuration::inputFilename,
|
||||
std::ios::in | std::ios::binary
|
||||
);
|
||||
|
||||
// A little bit of error handling
|
||||
if (!ifs.good()) {
|
||||
throw std::runtime_error("Unable to open infilestream!");
|
||||
}
|
||||
|
||||
// Redirect our istream to this infilestream
|
||||
in = &ifs;
|
||||
break;
|
||||
|
||||
// Are we reading from a parameter?
|
||||
case Configuration::INPUT_FROM::PARAMETER:
|
||||
|
||||
// Create an instringstream with our parameter
|
||||
iss = std::istringstream(
|
||||
CommandlineInterface::Get()["--intext"].GetString()
|
||||
);
|
||||
|
||||
// Redirect our istream to this instringstream
|
||||
in = &iss;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Derive from our the current module if we're reading ciphertext or not
|
||||
if (Configuration::activeModule == Configuration::MODULE::DECRYPTION) {
|
||||
isReadingCiphertext = true;
|
||||
}
|
||||
else {
|
||||
isReadingCiphertext = false;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
reachedEof = false;
|
||||
nBlocksRead = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DataIngestionLayer::Destruct() {
|
||||
|
||||
if (Configuration::inputFrom == Configuration::INPUT_FROM::FILE) {
|
||||
ifs.close();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DataIngestionLayer::ReadBlock() {
|
||||
if (!initialized) {
|
||||
throw std::runtime_error("Attempted to read on uninitialized DataIngestionLayer!");
|
||||
}
|
||||
|
||||
if (!reachedEof) {
|
||||
// A block is this many digits wide, in encoding
|
||||
const std::size_t blockWidth = blockLengthByBase[Configuration::formatIn];
|
||||
|
||||
// Iterate over the string, and parse all blocks
|
||||
// We now have to differentiate between single-char digit sets (like hex),
|
||||
// and multi-char digit sets (like uwu):
|
||||
switch (Configuration::formatIn) {
|
||||
case Configuration::IOBASE_FORMAT::BASE_BYTES:
|
||||
case Configuration::IOBASE_FORMAT::BASE_2:
|
||||
case Configuration::IOBASE_FORMAT::BASE_8:
|
||||
case Configuration::IOBASE_FORMAT::BASE_10:
|
||||
case Configuration::IOBASE_FORMAT::BASE_16:
|
||||
case Configuration::IOBASE_FORMAT::BASE_64: {
|
||||
// Easy case: Each digit is exactly one char in size.
|
||||
// We can just calculate how many bytes we have to read.
|
||||
|
||||
// bytesRead is always of the correct length, 0-padded.
|
||||
std::size_t n_bytes_read;
|
||||
const std::string dataRead = ReadBytes(blockWidth, n_bytes_read);
|
||||
|
||||
// If we've read 0 bytes, this was the last block
|
||||
// and it's completely empty. We can abort without doing anything.
|
||||
// The ReadBytes function takes care of setting the reachedEof flag.
|
||||
if (n_bytes_read == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we are reading ciphertext
|
||||
// make sure we've read enough bytes to compose a block.
|
||||
if (
|
||||
(isReadingCiphertext) &&
|
||||
(n_bytes_read < blockWidth)
|
||||
) {
|
||||
throw std::runtime_error("DataIngestionLayer::ReadBlock() read an input-data fragment that is smaller than a data block should be. Is your cipher text incomplete?");
|
||||
}
|
||||
|
||||
// This should decode to a block just like this.
|
||||
Block newBlock;
|
||||
|
||||
// Special-case: We are reading cleartext (no ciphertext)
|
||||
// cleartext is always base_bytes
|
||||
if (!isReadingCiphertext) {
|
||||
// When just reading cleartext-bytes, we also allow shorter strings
|
||||
// than BLOCK_SIZE. These will just get zero-padded.
|
||||
newBlock.FromTextString(dataRead);
|
||||
}
|
||||
else {
|
||||
// Else: recode to a block.
|
||||
newBlock = DataFormatter::DecodeFormat(
|
||||
dataRead,
|
||||
Configuration::formatIn
|
||||
);
|
||||
}
|
||||
|
||||
blocks.emplace(newBlock);
|
||||
nBlocksRead++;
|
||||
break;
|
||||
}
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_UWU:
|
||||
case Configuration::IOBASE_FORMAT::BASE_UGH: {
|
||||
// The whole of Italy doesn't have as much spaghetti as this is...
|
||||
|
||||
// Hard case: Each digit is n digits long. Digits may vary in length.
|
||||
// They are seperated by spaces.
|
||||
// We have to parse them...
|
||||
std::string overshoot = ""; // this is how much we've read too much in the last iteration
|
||||
|
||||
|
||||
// Gets terminated by a break statement
|
||||
while (1) {
|
||||
// We'll read chunks of 64 bytes... This should be a good
|
||||
// median, to also support small multi-byte-digit sets
|
||||
std::size_t n_bytes_read = 0;
|
||||
int lastDigitPos = -1; // Should point the the space BEFORE it. Relative to chunk.
|
||||
std::size_t digitsCollected = 0;
|
||||
std::stringstream digits;
|
||||
bool foundBlock = false;
|
||||
|
||||
// Remember to prepend our overshoot from the previous iteration this chunk
|
||||
std::string chunk = overshoot + ReadBytes(64, n_bytes_read);
|
||||
|
||||
// We should also strip all linebreaks from the chunk, that may be a result of manual stdin input.
|
||||
chunk = StringTools::Replace(chunk, '\n', "");
|
||||
|
||||
// We can't just check for completeness by n_bytes_read...
|
||||
// It can be any number of bytes, since any digit is n bytes long...
|
||||
|
||||
// Parse the 64-byte chunk string we've just fetched:
|
||||
for (std::size_t i = 0; i < chunk.size(); i++) {
|
||||
|
||||
// If we are near the end, and have still not found a complete block, let's load an additional chunk
|
||||
if (i == chunk.size() - 2) {
|
||||
const std::string nextChunk = ReadBytes(64, n_bytes_read);
|
||||
if (n_bytes_read != 0) {
|
||||
chunk += StringTools::Replace(nextChunk, '\n', "");
|
||||
}
|
||||
}
|
||||
|
||||
// If i is on a space, or at the end of the chunk,
|
||||
// and, at least one of i, or lastDigitPos is on a space,
|
||||
if (
|
||||
(
|
||||
(chunk[i] == ' ') ||
|
||||
(i == chunk.size() - 1)
|
||||
) &&
|
||||
(
|
||||
(chunk[i] == ' ') ||
|
||||
lastDigitPos >= 0 // This basically does the same as discribed, but safer, as its default value is -1.
|
||||
)
|
||||
){
|
||||
digitsCollected++;
|
||||
|
||||
// We have found a digit. Let's store it away...
|
||||
// We're putting them in a stringstream, to fit the format required by the data formatter...
|
||||
|
||||
// We have a slight edgecase if we're currently on the last char. Then we do NOT want to read one short.
|
||||
// This is because we ususally stand on a seperator char (' '), which we do not want to extract. But in that case,
|
||||
// in which we're standing on the last char, it could be not a seperator char.
|
||||
// note: chunk[i] != ' ' can only be true if we're on the last char.
|
||||
if (chunk[i] == ' ') {
|
||||
digits <<
|
||||
chunk.substr(
|
||||
lastDigitPos + 1,
|
||||
(int)i - lastDigitPos - 1
|
||||
)
|
||||
;
|
||||
} else {
|
||||
digits <<
|
||||
chunk.substr(
|
||||
lastDigitPos + 1,
|
||||
(int)i - lastDigitPos
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
// Add a seperator, if its not the last
|
||||
if (digitsCollected != blockWidth) {
|
||||
digits << ' ';
|
||||
}
|
||||
|
||||
lastDigitPos = i;
|
||||
|
||||
// Do we have enough digits to form a block?
|
||||
if (digitsCollected == blockWidth) {
|
||||
// We've found a complete block!
|
||||
|
||||
// Trim excess nullbytes off out digit string
|
||||
const std::string digitString = std::string(
|
||||
digits.str().data(),
|
||||
strlen(digits.str().data())
|
||||
);
|
||||
|
||||
// Decode it to a block object
|
||||
const Block newBlock = DataFormatter::DecodeFormat(
|
||||
digitString,
|
||||
Configuration::formatIn
|
||||
);
|
||||
|
||||
// Enqueue it to be processed by some module
|
||||
blocks.emplace(newBlock);
|
||||
nBlocksRead++;
|
||||
foundBlock = true;
|
||||
|
||||
// Now we have to calculate how many bytes we've read TOO MANY.
|
||||
// We have to trim this current chunk to be our new overshoot.
|
||||
|
||||
// If we still have more than a byte left, leave out the current seperator char
|
||||
if (i < chunk.size() - 1) {
|
||||
overshoot = chunk.substr(i+1); // Take all bytes from the next iterator, to the end
|
||||
}
|
||||
// Else: we are on the last char: there is no overshoot
|
||||
else {
|
||||
overshoot = "";
|
||||
}
|
||||
|
||||
// Stop the for loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Exit-condition:
|
||||
// We have not found any block, not even any digit.
|
||||
if ((!foundBlock) && (digitsCollected == 0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Hard-abort: We have not finished reading a block
|
||||
if (!foundBlock) {
|
||||
throw std::runtime_error("DataIngestionLayer reached EOF whilst parsing multi-byte-digit block...");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::invalid_argument("DataFormatter::StringToBlocks() has been passed an unknown base! No switch-case matched!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string DataIngestionLayer::ReadBytes(const std::size_t n, std::size_t& out_bytes_read) {
|
||||
|
||||
// Prepare a buffer to read to
|
||||
char* buf = new char[n+1];
|
||||
memset(buf, 0, (n+1) * sizeof(buf[0]));
|
||||
|
||||
// Read
|
||||
in->read(buf, n * sizeof(buf[0]));
|
||||
|
||||
// Fetch how much we've read
|
||||
out_bytes_read = in->gcount();
|
||||
|
||||
// Is this fewer bytes than got requested?
|
||||
if (out_bytes_read < n) {
|
||||
// Yes: EOF reached.
|
||||
reachedEof = true;
|
||||
}
|
||||
|
||||
// Translate buffer to a standard string
|
||||
const std::string sbuf(buf, n);
|
||||
delete[] buf;
|
||||
|
||||
// Return our buffer
|
||||
return sbuf;
|
||||
}
|
||||
|
||||
bool DataIngestionLayer::ReachedEOF() {
|
||||
return reachedEof;
|
||||
}
|
||||
|
||||
bool DataIngestionLayer::IsBlockReady() {
|
||||
// We're not ready, if we haven't reached EOF, if we should buffer
|
||||
// the input.
|
||||
if (
|
||||
(CommandlineInterface::Get().HasParam("--buffer-input")) &&
|
||||
(!reachedEof)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we're not buffering, just return whether or not
|
||||
// we have any blocks...
|
||||
return blocks.size() > 0;
|
||||
}
|
||||
|
||||
bool DataIngestionLayer::IsFinished() {
|
||||
return (reachedEof) && (blocks.size() == 0);
|
||||
}
|
||||
|
||||
Block DataIngestionLayer::GetNextBlock() {
|
||||
if (!IsBlockReady()) {
|
||||
throw std::runtime_error("Attempted to get the next block, but there are none left!");
|
||||
}
|
||||
|
||||
// Why... why not just return a T in pop()???
|
||||
const Block popped = blocks.front();
|
||||
blocks.pop();
|
||||
return popped;
|
||||
}
|
||||
|
||||
std::size_t DataIngestionLayer::NBlocksRead() {
|
||||
return nBlocksRead;
|
||||
}
|
||||
|
||||
std::istream* DataIngestionLayer::in;
|
||||
std::ifstream DataIngestionLayer::ifs;
|
||||
std::istringstream DataIngestionLayer::iss;
|
||||
bool DataIngestionLayer::reachedEof = false;
|
||||
bool DataIngestionLayer::initialized = false;
|
||||
bool DataIngestionLayer::isReadingCiphertext;
|
||||
std::size_t DataIngestionLayer::nBlocksRead = 0;
|
||||
std::queue<Block> DataIngestionLayer::blocks;
|
||||
|
@ -1,149 +0,0 @@
|
||||
#include "DataOutputLayer.h"
|
||||
#include "DataFormatter.h"
|
||||
#include "CommandlineInterface.h"
|
||||
#include <ostream>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace IO;
|
||||
|
||||
void DataOutputLayer::Init() {
|
||||
|
||||
// Set our ostream
|
||||
switch (Configuration::outputTo) {
|
||||
|
||||
// Are we writing to stdout?
|
||||
case Configuration::OUTPUT_TO::STDOUT:
|
||||
|
||||
// Redirect our ostream to stdout
|
||||
out = &std::cout;
|
||||
break;
|
||||
|
||||
// Are we writing to a file?
|
||||
case Configuration::OUTPUT_TO::FILE:
|
||||
|
||||
// Open the file
|
||||
ofs.open(
|
||||
Configuration::outputFilename,
|
||||
std::ios::out | std::ios::binary
|
||||
);
|
||||
|
||||
// A little bit of error handling
|
||||
if (!ofs.good()) {
|
||||
throw std::runtime_error("Unable to open outfilestream!");
|
||||
}
|
||||
|
||||
// Redirect our ostream to this outfilestream
|
||||
out = &ofs;
|
||||
break;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
reachedEof = false;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void DataOutputLayer::Destruct() {
|
||||
if (Configuration::outputTo == Configuration::OUTPUT_TO::FILE) {
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DataOutputLayer::Enqueue(const Block& block) {
|
||||
blocks.emplace(block);
|
||||
return;
|
||||
}
|
||||
|
||||
void DataOutputLayer::WriteBlock() {
|
||||
// Some error checking
|
||||
if (!initialized) {
|
||||
throw std::runtime_error("Attempted to write on uninitialized DataOutputLayer!");
|
||||
}
|
||||
|
||||
// Check if we have any block to write
|
||||
// and if we should (output-buffering)
|
||||
// Basically: only output if we have anything to output, and
|
||||
// if --buffer-output is given, only output once we have reachedEof.
|
||||
if (
|
||||
(blocks.size() > 0) &&
|
||||
(
|
||||
(!CommandlineInterface::Get().HasParam("--buffer-output")) ||
|
||||
(reachedEof)
|
||||
)
|
||||
) {
|
||||
// Fetch the block to write
|
||||
const Block block = blocks.front();
|
||||
blocks.pop();
|
||||
|
||||
// Recode it to our output format
|
||||
const std::string formattedBlock =
|
||||
DataFormatter::FormatBlock(
|
||||
block,
|
||||
Configuration::formatOut
|
||||
);
|
||||
|
||||
// Dump it
|
||||
// This way we avoid zerobytes getting trimmed off...
|
||||
out->write(formattedBlock.data(), formattedBlock.length());
|
||||
|
||||
// If this is not the last block, and the used iobase set
|
||||
// requires it, append a seperator
|
||||
if (
|
||||
(!IsFinished()) &&
|
||||
(
|
||||
(Configuration::formatOut == Configuration::IOBASE_FORMAT::BASE_UWU) ||
|
||||
(Configuration::formatOut == Configuration::IOBASE_FORMAT::BASE_UGH)
|
||||
)
|
||||
) {
|
||||
*out << " ";
|
||||
}
|
||||
|
||||
AddTrailingLinebreakIfRequired();
|
||||
out->flush();
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DataOutputLayer::ReachedEOF() {
|
||||
reachedEof = true;
|
||||
|
||||
// Add the trailing linebreak here aswell, as, if input is ciphertext,
|
||||
// ReachedEOF() may only be called after all blocks are already written
|
||||
AddTrailingLinebreakIfRequired();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool DataOutputLayer::IsFinished() {
|
||||
return (reachedEof) && (blocks.size() == 0);
|
||||
}
|
||||
|
||||
void DataOutputLayer::AddTrailingLinebreakIfRequired() {
|
||||
// If we are finished, and are outputting to stdout,
|
||||
// and input format is not bytes,
|
||||
// and the user didn't specifically opt out, print a newline
|
||||
if (
|
||||
(IsFinished()) &&
|
||||
(Configuration::outputTo == Configuration::OUTPUT_TO::STDOUT) &&
|
||||
(Configuration::formatOut != Configuration::IOBASE_FORMAT::BASE_BYTES) &&
|
||||
(!CommandlineInterface::Get().HasParam("--no-newline"))
|
||||
) {
|
||||
*out << std::endl;
|
||||
out->flush();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::ostream* DataOutputLayer::out;
|
||||
std::ofstream DataOutputLayer::ofs;
|
||||
bool DataOutputLayer::reachedEof = false;
|
||||
bool DataOutputLayer::initialized = false;
|
||||
std::queue<Block> DataOutputLayer::blocks;
|
||||
|
@ -1,107 +0,0 @@
|
||||
#include "KeyManager.h"
|
||||
#include "CommandlineInterface.h"
|
||||
#include "Configuration.h"
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
// Required for hidden password input
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
#include <Windows.h>
|
||||
#elif defined __GNUG__
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
void KeyManager::PrepareKey() {
|
||||
|
||||
// Special-case: We are hashing:
|
||||
// no key needed.
|
||||
if (Configuration::activeModule == Configuration::MODULE::HASH) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Special-case: We are generating a keyfile:
|
||||
// generate a random key from hardware events.
|
||||
else if (Configuration::activeModule == Configuration::MODULE::GENERATE_KEY) {
|
||||
key = Key::Random();
|
||||
return;
|
||||
}
|
||||
|
||||
// Else:
|
||||
// Is a password passed on the command line?
|
||||
else if (CommandlineInterface::Get().HasParam("--key")) {
|
||||
// Fetch it, and hash it to a key
|
||||
std::string password = CommandlineInterface::Get()["--key"].GetString();
|
||||
|
||||
key = Key::FromPassword(password);
|
||||
|
||||
// Don't forget to zero string memory.
|
||||
memset(password.data(), 0, password.size());
|
||||
return;
|
||||
}
|
||||
|
||||
// Should we prompt for a password on stdin?
|
||||
else if (CommandlineInterface::Get().HasParam("--keyask")) {
|
||||
// Create a password prompt
|
||||
std::string password = PasswordPrompt();
|
||||
|
||||
key = Key::FromPassword(password);
|
||||
|
||||
// Don't forget to zero string memory.
|
||||
memset(password.data(), 0, password.size());
|
||||
return;
|
||||
}
|
||||
|
||||
// Else:
|
||||
// Should we read from a keyfile?
|
||||
else if (CommandlineInterface::Get().HasParam("--keyfile")) {
|
||||
// Fetch the filename, and read it
|
||||
const std::string filepath = CommandlineInterface::Get()["--keyfile"].GetString();
|
||||
key = Key::LoadFromFile(filepath);
|
||||
return;
|
||||
}
|
||||
|
||||
throw std::runtime_error("No key option found. Is the CLI parser configuration correct?.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const Key& KeyManager::GetKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
std::string KeyManager::PasswordPrompt() {
|
||||
// Disable stdin-echo
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
DWORD mode = 0;
|
||||
GetConsoleMode(hStdin, &mode);
|
||||
SetConsoleMode(hStdin, mode & (~ENABLE_ECHO_INPUT));
|
||||
|
||||
#elif defined __GNUG__
|
||||
termios oldt;
|
||||
tcgetattr(STDIN_FILENO, &oldt);
|
||||
termios newt = oldt;
|
||||
newt.c_lflag &= ~ECHO;
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||||
|
||||
#endif
|
||||
|
||||
// Prompt stdin
|
||||
std::string password;
|
||||
std::cin >> password;
|
||||
|
||||
// Restore previous config
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
SetConsoleMode(hStdin, mode);
|
||||
|
||||
#elif defined __GNUG__
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||
#endif
|
||||
|
||||
return password;
|
||||
}
|
||||
|
||||
Key KeyManager::key;
|
||||
|
@ -1,67 +0,0 @@
|
||||
#include "ModuleDecryption.h"
|
||||
#include "DataIngestionLayer.h"
|
||||
#include "DataOutputLayer.h"
|
||||
#include "ProgressPrinter.h"
|
||||
#include "KeyManager.h"
|
||||
#include <GCrypt/GCipher.h>
|
||||
|
||||
using namespace Module;
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
void Decryption::Run() {
|
||||
|
||||
// Initialize the data ingestion layer
|
||||
IO::DataIngestionLayer::Init();
|
||||
|
||||
// Initialize the data output layer
|
||||
IO::DataOutputLayer::Init();
|
||||
|
||||
// Initialize a cipher
|
||||
GCipher cipher(
|
||||
KeyManager::GetKey(),
|
||||
GCipher::DIRECTION::DECIPHER
|
||||
);
|
||||
|
||||
std::size_t nBlocksDigested = 0;
|
||||
while (!IO::DataOutputLayer::IsFinished()) {
|
||||
// Read in new blocks, if not reached eof
|
||||
if (!IO::DataIngestionLayer::ReachedEOF()) {
|
||||
IO::DataIngestionLayer::ReadBlock();
|
||||
}
|
||||
|
||||
// Process a block, if one is ready
|
||||
if (IO::DataIngestionLayer::IsBlockReady()) {
|
||||
|
||||
// Print progress, if appropriate
|
||||
ProgressPrinter::PrintIfAppropriate(
|
||||
"Decrypting",
|
||||
nBlocksDigested,
|
||||
IO::DataIngestionLayer::NBlocksRead()
|
||||
);
|
||||
|
||||
const Block cleartext = IO::DataIngestionLayer::GetNextBlock();
|
||||
const Block ciphertext = cipher.Digest(cleartext);
|
||||
nBlocksDigested++;
|
||||
|
||||
// Enqueue the block for output
|
||||
IO::DataOutputLayer::Enqueue(ciphertext);
|
||||
}
|
||||
|
||||
// Tell the data output layer that it received the
|
||||
// last block, if it did
|
||||
if (IO::DataIngestionLayer::IsFinished()) {
|
||||
IO::DataOutputLayer::ReachedEOF();
|
||||
}
|
||||
|
||||
// Attempt to write a block
|
||||
IO::DataOutputLayer::WriteBlock();
|
||||
}
|
||||
|
||||
// Destruct the data ingestion layer
|
||||
IO::DataIngestionLayer::Destruct();
|
||||
|
||||
// Destruct the data output layer
|
||||
IO::DataOutputLayer::Destruct();
|
||||
|
||||
return;
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
#include "ModuleEncryption.h"
|
||||
#include "DataIngestionLayer.h"
|
||||
#include "DataOutputLayer.h"
|
||||
#include "KeyManager.h"
|
||||
#include "ProgressPrinter.h"
|
||||
#include <GCrypt/GCipher.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Module;
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
void Encryption::Run() {
|
||||
|
||||
// Initialize the data ingestion layer
|
||||
IO::DataIngestionLayer::Init();
|
||||
|
||||
// Initialize the data output layer
|
||||
IO::DataOutputLayer::Init();
|
||||
|
||||
// Initialize a cipher
|
||||
GCipher cipher(
|
||||
KeyManager::GetKey(),
|
||||
GCipher::DIRECTION::ENCIPHER
|
||||
);
|
||||
|
||||
std::size_t nBlocksDigested = 0;
|
||||
while (!IO::DataOutputLayer::IsFinished()) {
|
||||
// Read in new blocks, if not reached eof
|
||||
if (!IO::DataIngestionLayer::ReachedEOF()) {
|
||||
IO::DataIngestionLayer::ReadBlock();
|
||||
}
|
||||
|
||||
// Process a block, if one is ready
|
||||
if (IO::DataIngestionLayer::IsBlockReady()) {
|
||||
|
||||
// Print progress, if appropriate
|
||||
ProgressPrinter::PrintIfAppropriate(
|
||||
"Encrypting",
|
||||
nBlocksDigested,
|
||||
IO::DataIngestionLayer::NBlocksRead()
|
||||
);
|
||||
|
||||
const Block cleartext = IO::DataIngestionLayer::GetNextBlock();
|
||||
const Block ciphertext = cipher.Digest(cleartext);
|
||||
nBlocksDigested++;
|
||||
|
||||
// Enqueue the block for output
|
||||
IO::DataOutputLayer::Enqueue(ciphertext);
|
||||
}
|
||||
|
||||
// Tell the data output layer that it just received the
|
||||
// last block, if it did
|
||||
if (IO::DataIngestionLayer::IsFinished()) {
|
||||
IO::DataOutputLayer::ReachedEOF();
|
||||
}
|
||||
|
||||
// Attempt to write a block
|
||||
IO::DataOutputLayer::WriteBlock();
|
||||
}
|
||||
|
||||
// Destruct the data ingestion layer
|
||||
IO::DataIngestionLayer::Destruct();
|
||||
|
||||
// Destruct the data output layer
|
||||
IO::DataOutputLayer::Destruct();
|
||||
|
||||
return;
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
#include "ModuleGenerateKey.h"
|
||||
#include "DataOutputLayer.h"
|
||||
#include "KeyManager.h"
|
||||
#include "CommandlineInterface.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
using namespace Module;
|
||||
|
||||
void GenerateKey::Run() {
|
||||
|
||||
// Initialize the data output layer
|
||||
IO::DataOutputLayer::Init();
|
||||
|
||||
// Enqueue our single block of data
|
||||
IO::DataOutputLayer::Enqueue(KeyManager::GetKey());
|
||||
|
||||
// Tell the data output layer, that is has received all blocks
|
||||
IO::DataOutputLayer::ReachedEOF();
|
||||
|
||||
// Tell it to write all blocks
|
||||
// (a single call should suffice, but a while-loop is the proper
|
||||
// way to do it)
|
||||
while (!IO::DataOutputLayer::IsFinished()) {
|
||||
IO::DataOutputLayer::WriteBlock();
|
||||
}
|
||||
|
||||
// Destruct the data output layer
|
||||
IO::DataOutputLayer::Destruct();
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1,64 +0,0 @@
|
||||
#include "ModuleHashing.h"
|
||||
#include "DataIngestionLayer.h"
|
||||
#include "DataOutputLayer.h"
|
||||
#include "ProgressPrinter.h"
|
||||
#include "KeyManager.h"
|
||||
#include <GCrypt/GHash.h>
|
||||
|
||||
using namespace Module;
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
void Hashing::Run() {
|
||||
|
||||
// Initialize the data ingestion layer
|
||||
IO::DataIngestionLayer::Init();
|
||||
|
||||
// Initialize the data output layer
|
||||
IO::DataOutputLayer::Init();
|
||||
|
||||
// Initialize a ghasher
|
||||
GHash hasher;
|
||||
|
||||
// Read in new blocks, if not reached eof
|
||||
std::size_t nBlocksDigested = 0;
|
||||
while (!IO::DataIngestionLayer::IsFinished()) {
|
||||
if (!IO::DataIngestionLayer::ReachedEOF()) {
|
||||
IO::DataIngestionLayer::ReadBlock();
|
||||
}
|
||||
|
||||
// Process a block, if one is ready
|
||||
if (IO::DataIngestionLayer::IsBlockReady()) {
|
||||
|
||||
// Print progress, if appropriate
|
||||
ProgressPrinter::PrintIfAppropriate(
|
||||
"Hashing",
|
||||
nBlocksDigested,
|
||||
IO::DataIngestionLayer::NBlocksRead()
|
||||
);
|
||||
|
||||
const Block cleartext = IO::DataIngestionLayer::GetNextBlock();
|
||||
hasher.Digest(cleartext);
|
||||
nBlocksDigested++;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until we've finished digesting all blocks
|
||||
// Enqueue that single block (the hash result) to the output layer
|
||||
IO::DataOutputLayer::Enqueue(hasher.GetHashsum());
|
||||
|
||||
// Tell the data output layer that that was the last block
|
||||
IO::DataOutputLayer::ReachedEOF();
|
||||
|
||||
// Dump it
|
||||
while (!IO::DataOutputLayer::IsFinished()) {
|
||||
IO::DataOutputLayer::WriteBlock();
|
||||
}
|
||||
|
||||
// Destruct the data ingestion layer
|
||||
IO::DataIngestionLayer::Destruct();
|
||||
|
||||
// Destruct the data output layer
|
||||
IO::DataOutputLayer::Destruct();
|
||||
|
||||
return;
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#include "ProgressPrinter.h"
|
||||
#include "CommandlineInterface.h"
|
||||
#include <iostream>
|
||||
|
||||
void ProgressPrinter::PrintIfAppropriate(
|
||||
const std::string& message,
|
||||
const std::size_t current,
|
||||
const std::size_t target
|
||||
) {
|
||||
if (
|
||||
(CommandlineInterface::Get().HasParam("--progress")) &&
|
||||
(current % CommandlineInterface::Get()["--progress-interval"].GetInt32() == 0)
|
||||
) {
|
||||
std::cerr
|
||||
<< message
|
||||
<< "... (Block "
|
||||
<< current + 1
|
||||
<< " / "
|
||||
<< target
|
||||
<< " - " << ((float)(current+1)*100 / target)
|
||||
<< "%)"
|
||||
<< std::endl
|
||||
;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
#include "CommandlineInterface.h"
|
||||
#include "Configuration.h"
|
||||
#include "KeyManager.h"
|
||||
#include "ModuleGenerateKey.h"
|
||||
#include "ModuleEncryption.h"
|
||||
#include "ModuleDecryption.h"
|
||||
#include "ModuleHashing.h"
|
||||
|
||||
int main(int argc, char* const* argv) {
|
||||
|
||||
// Init cli args
|
||||
CommandlineInterface::Init(argc, argv);
|
||||
|
||||
// Parse configuration
|
||||
Configuration::Parse();
|
||||
|
||||
// Prepare the key
|
||||
KeyManager::PrepareKey();
|
||||
|
||||
// Launch our module
|
||||
switch (Configuration::activeModule) {
|
||||
case Configuration::MODULE::ENCRYPTION:
|
||||
Module::Encryption::Run();
|
||||
break;
|
||||
|
||||
case Configuration::MODULE::DECRYPTION:
|
||||
Module::Decryption::Run();
|
||||
break;
|
||||
|
||||
case Configuration::MODULE::GENERATE_KEY:
|
||||
Module::GenerateKey::Run();
|
||||
break;
|
||||
|
||||
case Configuration::MODULE::HASH:
|
||||
Module::Hashing::Run();
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
17965
GCryptCLI/test/Catch2.h
@ -1,90 +0,0 @@
|
||||
#include <DataFormatter.h>
|
||||
#include <GCrypt/Key.h>
|
||||
#include <GCrypt/GPrng.h>
|
||||
#include "Catch2.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
// Tests that recoding iobase formats works for individual blocks, with random data
|
||||
TEMPLATE_TEST_CASE_SIG(
|
||||
__FILE__"Data formats can be converted, without changing in value, with indivudual blocks, with random data",
|
||||
"[DataFormatter]",
|
||||
((Configuration::IOBASE_FORMAT formatUnderTest), formatUnderTest),
|
||||
Configuration::IOBASE_FORMAT::BASE_BYTES,
|
||||
Configuration::IOBASE_FORMAT::BASE_2,
|
||||
Configuration::IOBASE_FORMAT::BASE_8,
|
||||
Configuration::IOBASE_FORMAT::BASE_10,
|
||||
Configuration::IOBASE_FORMAT::BASE_16,
|
||||
Configuration::IOBASE_FORMAT::BASE_64,
|
||||
Configuration::IOBASE_FORMAT::BASE_UWU,
|
||||
Configuration::IOBASE_FORMAT::BASE_UGH
|
||||
) {
|
||||
|
||||
// Let's use a GPrng instead of Key::Random,
|
||||
// because Key::Random is rather slow (because it's using hardware events).
|
||||
// We just want randomized data for tests...
|
||||
|
||||
GPrng prng(Key::Random());
|
||||
|
||||
// Let's try 10 different random blocks per test
|
||||
for (std::size_t i = 0; i < 10; i++) {
|
||||
|
||||
// Setup
|
||||
const Block b_initial = prng.GetBlock();
|
||||
|
||||
// Exercise
|
||||
// Convert to a custom base
|
||||
const std::string b_format = DataFormatter::FormatBlock(
|
||||
b_initial,
|
||||
formatUnderTest
|
||||
);
|
||||
|
||||
// Convert back to a block
|
||||
const Block b_retrieved = DataFormatter::DecodeFormat(
|
||||
b_format,
|
||||
formatUnderTest
|
||||
);
|
||||
|
||||
// Verify
|
||||
// Do b_initial and b_retrieved match?
|
||||
REQUIRE(b_initial == b_retrieved);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that recoding iobase format works
|
||||
TEMPLATE_TEST_CASE_SIG(
|
||||
__FILE__"Data formats can be converted, without changing in value, with indivudual blocks, with very little data (lots of nullbytes)",
|
||||
"[DataFormatter]",
|
||||
((Configuration::IOBASE_FORMAT formatUnderTest), formatUnderTest),
|
||||
Configuration::IOBASE_FORMAT::BASE_BYTES,
|
||||
Configuration::IOBASE_FORMAT::BASE_2,
|
||||
Configuration::IOBASE_FORMAT::BASE_8,
|
||||
Configuration::IOBASE_FORMAT::BASE_10,
|
||||
Configuration::IOBASE_FORMAT::BASE_16,
|
||||
Configuration::IOBASE_FORMAT::BASE_64,
|
||||
Configuration::IOBASE_FORMAT::BASE_UWU,
|
||||
Configuration::IOBASE_FORMAT::BASE_UGH
|
||||
) {
|
||||
|
||||
// Setup
|
||||
Block b_initial;
|
||||
b_initial.FromTextString("Heyu");
|
||||
|
||||
// Exercise
|
||||
// Convert to a custom base
|
||||
const std::string b_format = DataFormatter::FormatBlock(
|
||||
b_initial,
|
||||
formatUnderTest
|
||||
);
|
||||
|
||||
// Convert back to a block
|
||||
const Block b_retrieved = DataFormatter::DecodeFormat(
|
||||
b_format,
|
||||
formatUnderTest
|
||||
);
|
||||
|
||||
// Verify
|
||||
// Do b_initial and b_retrieved match?
|
||||
REQUIRE(b_initial == b_retrieved);
|
||||
}
|
||||
|
@ -1,2 +0,0 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "Catch2.h"
|
@ -1,86 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(GCrypt)
|
||||
|
||||
###################
|
||||
# Library project #
|
||||
###################
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
FILE(GLOB main_src src/*.cpp)
|
||||
add_library(${PROJECT_NAME}
|
||||
${main_src}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
include
|
||||
)
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE
|
||||
-Werror
|
||||
-fdiagnostics-color=always
|
||||
)
|
||||
|
||||
#########
|
||||
# Tests #
|
||||
#########
|
||||
FILE(GLOB test_src test/*.cpp)
|
||||
add_executable(test
|
||||
test/Catch2.h
|
||||
${test_src}
|
||||
)
|
||||
target_link_libraries(test ${PROJECT_NAME})
|
||||
|
||||
target_include_directories(test PRIVATE
|
||||
include
|
||||
)
|
||||
|
||||
target_compile_options(test PRIVATE
|
||||
-Werror
|
||||
-fdiagnostics-color=always
|
||||
)
|
||||
|
||||
|
||||
## Move test assest to build dir
|
||||
ADD_CUSTOM_COMMAND(
|
||||
TARGET ${PROJECT_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_SOURCE_DIR}/test/testAssets/ $<TARGET_FILE_DIR:${PROJECT_NAME}>/testAssets/
|
||||
)
|
||||
|
||||
|
||||
###############
|
||||
# Executables #
|
||||
###############
|
||||
FILE(GLOB bmpp_src exec/BmpPP/BmpPP/src/*.cpp)
|
||||
FILE(GLOB eule_src exec/Eule/Eule/src/*.cpp)
|
||||
add_compile_definitions(_EULE_NO_INTRINSICS_)
|
||||
include_directories(
|
||||
include
|
||||
exec/BmpPP/BmpPP/include
|
||||
exec/Eule/Eule/include
|
||||
)
|
||||
|
||||
## Move exec assets to build dir
|
||||
ADD_CUSTOM_COMMAND(
|
||||
TARGET ${PROJECT_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_SOURCE_DIR}/exec/execAssets/ $<TARGET_FILE_DIR:${PROJECT_NAME}>/execAssets/
|
||||
)
|
||||
|
||||
function(DECLARE_EXEC_EXAMPLE name)
|
||||
add_executable(example-${name} exec/${name}.cpp ${bmpp_src} ${eule_src})
|
||||
target_link_libraries(example-${name} ${PROJECT_NAME})
|
||||
target_compile_options(example-${name} PRIVATE -Werror -fdiagnostics-color=always)
|
||||
endfunction()
|
||||
|
||||
# These are the names of the cpp files in /exec/, without the ".cpp".
|
||||
DECLARE_EXEC_EXAMPLE(encrypt-decrypt-files)
|
||||
DECLARE_EXEC_EXAMPLE(encrypt-decrypt-strings)
|
||||
DECLARE_EXEC_EXAMPLE(benchmark-encryption)
|
||||
DECLARE_EXEC_EXAMPLE(benchmark-prng)
|
||||
DECLARE_EXEC_EXAMPLE(visualize-singleblock-diffusion)
|
||||
DECLARE_EXEC_EXAMPLE(visualize-multiblock-diffusion)
|
||||
DECLARE_EXEC_EXAMPLE(visualize-extreme-input-diffusion)
|
||||
DECLARE_EXEC_EXAMPLE(visualize-prng-distribution)
|
||||
DECLARE_EXEC_EXAMPLE(visualize-hashing-distribution)
|
||||
|
@ -1,21 +0,0 @@
|
||||
Old way (400 rounds, no matrix mult): 38.01s
|
||||
- 400 was the minimum for good diffusion
|
||||
|
||||
New way (10 rounds, with matrix mult): 1.16s
|
||||
- 10 rounds now give sufficient diffusion
|
||||
- still using bitsets and strings
|
||||
|
||||
With new block class (instead of bitsets) (10 rounds): 0.35s
|
||||
- still partially using bitsets and strings
|
||||
|
||||
With new block class (6 rounds, still good diffusion): 0.21s
|
||||
|
||||
With new templated block class (full block and half block): 0.14s
|
||||
- finally no more bitsets
|
||||
|
||||
With new sbox, reduction, and expansion function: 0.03s
|
||||
|
||||
With additional jumbling in feistel rounds: 0.03s
|
||||
|
||||
With direct file reading/writing from data blocks: 0.02s
|
||||
|
1
GCryptLib/doxygen/.gitignore
vendored
@ -1 +0,0 @@
|
||||
build/
|
@ -1,10 +0,0 @@
|
||||
all:
|
||||
# Copy all but the header of the readme here
|
||||
tail ../../readme.md -n +9 > index.md
|
||||
#
|
||||
# Run doxygen
|
||||
doxygen doxyfig
|
||||
#
|
||||
# Cleanup index.md
|
||||
rm index.md
|
||||
|
@ -1,23 +0,0 @@
|
||||
#ifndef GCRYPTEXAMPLE_BENCHMARK_H
|
||||
#define GCRYPTEXAMPLE_BENCHMARK_H
|
||||
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
void Benchmark(const std::string& brief, std::function<void()> toBenchmark) {
|
||||
std::cout << "Benchmarking " << brief << "..." << std::endl;
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
|
||||
toBenchmark();
|
||||
|
||||
auto end = std::chrono::steady_clock::now();
|
||||
double seconds = (double)std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() / 1000.0;
|
||||
std::cout << seconds << " seconds." << std::endl << std::endl;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit 522f9551ae31215cf63fcad88cacbfc8c818ccaf
|
@ -1 +0,0 @@
|
||||
Subproject commit 1bfd756aa8bd1d484857735d63b4fdf8a15bbed5
|
@ -1,58 +0,0 @@
|
||||
#ifndef GCRYPTEXAMPLE_VISUALIZE_H
|
||||
#define GCRYPTEXAMPLE_VISUALIZE_H
|
||||
|
||||
#include <GCrypt/Block.h>
|
||||
#include <BmpPP/Bmp.h>
|
||||
#include <string>
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
using namespace Leonetienne::Eule;
|
||||
using namespace Leonetienne::BmpPP;
|
||||
|
||||
void VisualizeBlock(const Block& block, const std::string& name) {
|
||||
BMP bmp(Vector2i(32, 16), Colormode::RGB);
|
||||
|
||||
std::size_t i = 0;
|
||||
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
|
||||
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
|
||||
const std::uint8_t pixel = block.GetBit(i) == false ? 255 : 0;
|
||||
bmp.SetPixel(Vector2i(x, y), pixel);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
bmp.Write(name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// size.x*size.y MUST equal blocks.size() * Block::BLOCK_SIZE_BITS. That should be, by defalt blocks.size * 512.
|
||||
void VisualizeBlocks(const std::vector<Block>& blocks, const Vector2i& size, const std::string& name) {
|
||||
|
||||
//! A bit of error checking...
|
||||
if (size.x*size.y != blocks.size() * Block::BLOCK_SIZE_BITS) {
|
||||
throw std::invalid_argument("Supplied unfitting widht/height for visualization. Does not fit bits!");
|
||||
}
|
||||
|
||||
BMP bmp(size, Colormode::RGB);
|
||||
|
||||
std::size_t i = 0;
|
||||
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
|
||||
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
|
||||
|
||||
const std::size_t blockIndex = i / Block::BLOCK_SIZE_BITS;
|
||||
const std::size_t relBitIndex = i - blockIndex * Block::BLOCK_SIZE_BITS;
|
||||
|
||||
const std::uint8_t pixel = blocks[blockIndex].GetBit(relBitIndex) == false ? 255 : 0;
|
||||
bmp.SetPixel(Vector2i(x, y), pixel);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
bmp.Write(name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,21 +0,0 @@
|
||||
#include <GCrypt/GWrapper.h>
|
||||
#include "Benchmark.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
int main() {
|
||||
|
||||
Benchmark(
|
||||
"file encryption",
|
||||
[]() {
|
||||
GWrapper::EncryptFile(
|
||||
"./execAssets/big-testfile.bmp",
|
||||
"./execAssets/testimage.bmp.crypt",
|
||||
Key::FromPassword("password1")
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,42 +0,0 @@
|
||||
#include <GCrypt/GPrng.h>
|
||||
#include <iostream>
|
||||
#include "Benchmark.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
int main() {
|
||||
|
||||
Benchmark(
|
||||
"generating 1.000.000 32-bit uints using prng.GetRandom<uint32_t>()",
|
||||
[]() {
|
||||
GPrng prng(Key::Random());
|
||||
for (int i = 0; i < 1000000; i++) {
|
||||
prng.GetRandom<std::uint32_t>();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Benchmark(
|
||||
"generating 1.000.000 uint32_t using prng()",
|
||||
[]() {
|
||||
GPrng prng(Key::Random());
|
||||
for (int i = 0; i < 1000000; i++) {
|
||||
prng();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Benchmark(
|
||||
"generating 100.000 data blocks using prng.GetBlock()",
|
||||
[]() {
|
||||
GPrng prng(Key::Random());
|
||||
for (int i = 0; i < 100000; i++) {
|
||||
prng.GetBlock();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,25 +0,0 @@
|
||||
#include <GCrypt/GWrapper.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
int main() {
|
||||
std::cout << "Example on how to encrypt & decrypt any file:" << std::endl;
|
||||
|
||||
// Encrypt
|
||||
GWrapper::EncryptFile(
|
||||
"./execAssets/testimage.bmp",
|
||||
"./execAssets/testimage.bmp.crypt",
|
||||
Key::FromPassword("password1")
|
||||
);
|
||||
|
||||
// Decrypt
|
||||
GWrapper::DecryptFile(
|
||||
"./execAssets/testimage.bmp.crypt",
|
||||
"./execAssets/testimage.bmp.clear.bmp",
|
||||
Key::FromPassword("password1"
|
||||
));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,30 +0,0 @@
|
||||
#include <GCrypt/GWrapper.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
int main() {
|
||||
std::cout << "Example on how to encrypt & decrypt strings:" << std::endl;
|
||||
|
||||
const std::string cleartext = "Hello, World :3";
|
||||
std::cout << "Cleartext: " << cleartext << std::endl;
|
||||
|
||||
// Encrypt
|
||||
const std::string ciphertext = GWrapper::EncryptString(
|
||||
cleartext,
|
||||
Key::FromPassword("password1")
|
||||
);
|
||||
|
||||
std::cout << "Ciphertext: " << ciphertext << std::endl;
|
||||
|
||||
// Decrypt
|
||||
const std::string decrypted = GWrapper::DecryptString(
|
||||
ciphertext,
|
||||
Key::FromPassword("password1")
|
||||
);
|
||||
|
||||
std::cout << "Decrypted: " << decrypted << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 10 MiB |
Before Width: | Height: | Size: 108 KiB |
@ -1,54 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <GCrypt/GWrapper.h>
|
||||
#include <GCrypt/Key.h>
|
||||
#include <GCrypt/Util.h>
|
||||
#include <BmpPP/Bmp.h>
|
||||
#include "Visualize.h"
|
||||
|
||||
const std::string execName = "visualize-extreme-input-diffusion";
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
using namespace Leonetienne::BmpPP;
|
||||
using namespace Leonetienne::Eule;
|
||||
|
||||
int main() {
|
||||
// These are magic values, which work for this specific input string.
|
||||
// If you want to try another string, get the size of all blocks in bits (it gets printed),
|
||||
// and find two integer factors which factor up to it. These are your images width, and height.
|
||||
const Vector2i visualizationDimension = Vector2i(56, 64);
|
||||
|
||||
|
||||
// Create a key
|
||||
// The key is almost just zeores (it doesn't have an IV, so what you see is what goes in the cipher.)
|
||||
// In case you're wondering, I can tell you right now that an all-zero input with an all-zero key will result in an all-zero ciphertext.
|
||||
Key key;
|
||||
key.Reset();
|
||||
key.SetBit(199, true);
|
||||
VisualizeBlock(key, execName+"-key.bmp");
|
||||
|
||||
// Create our input blocks
|
||||
// All the input blocks are just zeroes!
|
||||
std::vector<Block> input_blocks;
|
||||
input_blocks.resize(7);
|
||||
for (Block& block : input_blocks) {
|
||||
block.Reset();
|
||||
}
|
||||
|
||||
std::cout << "Input size is " << input_blocks.size() * Block::BLOCK_SIZE_BITS << " bits long." << std::endl;
|
||||
VisualizeBlocks(input_blocks, visualizationDimension, execName+"-input.bmp");
|
||||
|
||||
// Encrypt it
|
||||
std::vector<Block> ciphertext_blocks = GWrapper::CipherBlocks(input_blocks, key, GCipher::DIRECTION::ENCIPHER);
|
||||
VisualizeBlocks(ciphertext_blocks, visualizationDimension, execName+"-output.bmp");
|
||||
|
||||
// Now flip a single bit in the input
|
||||
input_blocks[3].FlipBit(156);
|
||||
VisualizeBlocks(input_blocks, visualizationDimension, execName+"-input-flip.bmp");
|
||||
|
||||
// Encrypt it again
|
||||
ciphertext_blocks = GWrapper::CipherBlocks(input_blocks, key, GCipher::DIRECTION::ENCIPHER);
|
||||
VisualizeBlocks(ciphertext_blocks, visualizationDimension, execName+"-output-flip.bmp");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,34 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <GCrypt/GHash.h>
|
||||
#include <BmpPP/Bmp.h>
|
||||
#include "Visualize.h"
|
||||
|
||||
const std::string execName = "visualize-hashing-distribution";
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
using namespace Leonetienne::BmpPP;
|
||||
using namespace Leonetienne::Eule;
|
||||
|
||||
void HashAndVisualize(const Block& b, const std::string filename) {
|
||||
GHash hasher;
|
||||
hasher.Digest(b);
|
||||
VisualizeBlock(hasher.GetHashsum(), filename);
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
// Get some random input
|
||||
Block a;
|
||||
a.FromTextString("Hello, World :3");
|
||||
VisualizeBlock(a, execName+"-input-a.bmp");
|
||||
HashAndVisualize(a, execName+"-output-a.bmp");
|
||||
|
||||
// Now flip a bit
|
||||
Block b = a;
|
||||
b.FlipBit(4);
|
||||
VisualizeBlock(b, execName+"-input-b.bmp");
|
||||
HashAndVisualize(b, execName+"-output-b.bmp");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,45 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <GCrypt/GWrapper.h>
|
||||
#include <GCrypt/Key.h>
|
||||
#include <GCrypt/Util.h>
|
||||
#include <BmpPP/Bmp.h>
|
||||
#include "Visualize.h"
|
||||
|
||||
const std::string execName = "visualize-multiblock-diffusion";
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
using namespace Leonetienne::BmpPP;
|
||||
using namespace Leonetienne::Eule;
|
||||
|
||||
int main() {
|
||||
// These are magic values, which work for this specific input string.
|
||||
// If you want to try another string, get the size of all blocks in bits (it gets printed),
|
||||
// and find two integer factors which factor up to it. These are your images width, and height.
|
||||
const Vector2i visualizationDimension = Vector2i(56, 64);
|
||||
|
||||
|
||||
// Create a key
|
||||
const Key key = Key::Random();
|
||||
VisualizeBlock(key, execName+"-key.bmp");
|
||||
|
||||
// Create our input blocks
|
||||
const std::string input = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
|
||||
std::vector<Block> input_blocks = StringToBitblocks(input);
|
||||
std::cout << "Input size is " << input_blocks.size() * Block::BLOCK_SIZE_BITS << " bits long." << std::endl;
|
||||
VisualizeBlocks(input_blocks, visualizationDimension, execName+"-input.bmp");
|
||||
|
||||
// Encrypt it
|
||||
std::vector<Block> ciphertext_blocks = GWrapper::CipherBlocks(input_blocks, key, GCipher::DIRECTION::ENCIPHER);
|
||||
VisualizeBlocks(ciphertext_blocks, visualizationDimension, execName+"-output.bmp");
|
||||
|
||||
// Now flip a single bit in the input
|
||||
input_blocks[3].FlipBit(156);
|
||||
VisualizeBlocks(input_blocks, visualizationDimension, execName+"-input-flip.bmp");
|
||||
|
||||
// Encrypt it again
|
||||
ciphertext_blocks = GWrapper::CipherBlocks(input_blocks, key, GCipher::DIRECTION::ENCIPHER);
|
||||
VisualizeBlocks(ciphertext_blocks, visualizationDimension, execName+"-output-flip.bmp");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,146 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <GCrypt/Key.h>
|
||||
#include <GCrypt/GPrng.h>
|
||||
#include <BmpPP/Bmp.h>
|
||||
#include "Benchmark.h"
|
||||
|
||||
const std::string execName = "visualize-prng-distribution";
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
using namespace Leonetienne::BmpPP;
|
||||
using namespace Leonetienne::Eule;
|
||||
|
||||
int main() {
|
||||
|
||||
// Black/white
|
||||
Benchmark(
|
||||
"black/white - GetBit()",
|
||||
[]() {
|
||||
Key seed = Key::Random();
|
||||
BMP bmp(Vector2i(800, 800), Colormode::RGB);
|
||||
GPrng prng(seed);
|
||||
|
||||
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
|
||||
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
|
||||
const std::uint8_t pixel = prng.GetBit() ? 255 : 0;
|
||||
bmp.SetPixel(Vector2i(x, y), pixel);
|
||||
}
|
||||
|
||||
bmp.Write(execName+"-blackwhite.bmp");
|
||||
}
|
||||
);
|
||||
|
||||
// Grayscale (using GetRandom<>)
|
||||
Benchmark(
|
||||
"grayscale - GetRandom<std::uint8_t>()",
|
||||
[]() {
|
||||
Key seed = Key::Random();
|
||||
BMP bmp(Vector2i(800, 800), Colormode::RGB);
|
||||
GPrng prng(seed);
|
||||
|
||||
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
|
||||
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
|
||||
const std::uint8_t pixel = prng.GetRandom<std::uint8_t>();
|
||||
bmp.SetPixel(Vector2i(x, y), pixel);
|
||||
}
|
||||
|
||||
bmp.Write(execName+"-getrandom-grayscale.bmp");
|
||||
}
|
||||
);
|
||||
|
||||
// Grayscale (using operator()) (this one returns a whole uint32)
|
||||
Benchmark(
|
||||
"grayscale - operator()",
|
||||
[]() {
|
||||
Key seed = Key::Random();
|
||||
BMP bmp(Vector2i(800, 800), Colormode::RGB);
|
||||
GPrng prng(seed);
|
||||
|
||||
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
|
||||
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
|
||||
const std::uint8_t pixel = prng() % 256;
|
||||
bmp.SetPixel(Vector2i(x, y), pixel);
|
||||
}
|
||||
|
||||
bmp.Write(execName+"-operator-grayscale.bmp");
|
||||
}
|
||||
);
|
||||
|
||||
// Color (using GetRandom<>)
|
||||
Benchmark(
|
||||
"color - GetRandom<uint8_t>()",
|
||||
[]() {
|
||||
Key seed = Key::Random();
|
||||
BMP bmp(Vector2i(800, 800), Colormode::RGB);
|
||||
GPrng prng(seed);
|
||||
|
||||
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
|
||||
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
|
||||
const std::uint8_t r = prng.GetRandom<std::uint8_t>();
|
||||
const std::uint8_t g = prng.GetRandom<std::uint8_t>();
|
||||
const std::uint8_t b = prng.GetRandom<std::uint8_t>();
|
||||
bmp.SetPixel(Vector2i(x, y), r, g, b);
|
||||
}
|
||||
|
||||
bmp.Write(execName+"-getrandom-color.bmp");
|
||||
}
|
||||
);
|
||||
|
||||
// Color (using operator()) (this one returns a whole uint32)
|
||||
Benchmark(
|
||||
"color - operator()",
|
||||
[]() {
|
||||
Key seed = Key::Random();
|
||||
BMP bmp(Vector2i(800, 800), Colormode::RGB);
|
||||
GPrng prng(seed);
|
||||
|
||||
for (std::size_t x = 0; x < bmp.GetDimensions().x; x++)
|
||||
for (std::size_t y = 0; y < bmp.GetDimensions().y; y++) {
|
||||
const std::uint8_t r = prng() % 256;
|
||||
const std::uint8_t g = prng() % 256;
|
||||
const std::uint8_t b = prng() % 256;
|
||||
bmp.SetPixel(Vector2i(x, y), r, g, b);
|
||||
}
|
||||
|
||||
bmp.Write(execName+"-operator-color.bmp");
|
||||
}
|
||||
);
|
||||
|
||||
// Color (using GetBlock())
|
||||
//(this one returns a derivation of the current hashsum, without using up randomness)
|
||||
Benchmark(
|
||||
"color - GetBlock()",
|
||||
[]() {
|
||||
Key seed = Key::Random();
|
||||
BMP bmp(Vector2i(800, 800), Colormode::RGB);
|
||||
GPrng prng(seed);
|
||||
|
||||
std::size_t bytes_written = 0;
|
||||
while (bytes_written < bmp.GetPixelbufferSize()) {
|
||||
const Block block = prng.GetBlock();
|
||||
|
||||
std::size_t bytesToCopy = 0;
|
||||
if (bmp.GetPixelbufferSize() - bytes_written < Block::BLOCK_SIZE) {
|
||||
bytesToCopy = bmp.GetPixelbufferSize() - bytes_written;
|
||||
}
|
||||
else {
|
||||
bytesToCopy = Block::BLOCK_SIZE;
|
||||
}
|
||||
|
||||
memcpy(
|
||||
(char*)bmp.GetPixelbuffer().data() + bytes_written,
|
||||
(char*)block.Data(),
|
||||
bytesToCopy
|
||||
);
|
||||
|
||||
bytes_written += bytesToCopy;
|
||||
|
||||
}
|
||||
|
||||
bmp.Write(execName+"-getblock-color.bmp");
|
||||
}
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,45 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <GCrypt/GWrapper.h>
|
||||
#include <GCrypt/Key.h>
|
||||
#include <BmpPP/Bmp.h>
|
||||
#include "Visualize.h"
|
||||
|
||||
const std::string execName = "visualize-singleblock-diffusion";
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
using namespace Leonetienne::BmpPP;
|
||||
using namespace Leonetienne::Eule;
|
||||
|
||||
int main() {
|
||||
|
||||
// Create input block
|
||||
const std::string input_str = "Hello :3";
|
||||
Block input;
|
||||
input.FromTextString(input_str);
|
||||
VisualizeBlock(input, execName+"-input.bmp");
|
||||
|
||||
// Create a key
|
||||
const Key key = Key::Random();
|
||||
VisualizeBlock(key, execName+"-key.bmp");
|
||||
|
||||
// Create a cipher
|
||||
GCipher cipher(key, GCipher::DIRECTION::ENCIPHER);
|
||||
|
||||
// Encipher our block
|
||||
Block cipherblock = cipher.Digest(input);
|
||||
VisualizeBlock(cipherblock, execName+"-output.bmp");
|
||||
|
||||
// Now flip a bit in the input
|
||||
input.FlipBit(35);
|
||||
VisualizeBlock(input, execName+"-input-flip.bmp");
|
||||
|
||||
// Reset our cipher, and encipher the input with a flipped bit
|
||||
cipher.Initialize(key, GCipher::DIRECTION::ENCIPHER);
|
||||
|
||||
// Encipher our block
|
||||
cipherblock = cipher.Digest(input);
|
||||
VisualizeBlock(cipherblock, execName+"-output-flip.bmp");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,216 +0,0 @@
|
||||
#ifndef GCRYPT_BLOCK_H
|
||||
#define GCRYPT_BLOCK_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
#include <bitset>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
/** This class represents a block of data,
|
||||
* and provides functions to manipulate it
|
||||
*/
|
||||
template <typename T>
|
||||
class Basic_Block {
|
||||
public:
|
||||
//! Will constuct an uninitialized data block
|
||||
Basic_Block();
|
||||
|
||||
//! Will construct this block from a string like "101010".. Length MUST be 512.
|
||||
Basic_Block(const std::string& other);
|
||||
|
||||
//! Copy-ctor
|
||||
Basic_Block(const Basic_Block<T>& other);
|
||||
|
||||
~Basic_Block();
|
||||
|
||||
//! Will construct this block from a string like "011101..".
|
||||
void FromBinaryString(const std::string& str);
|
||||
|
||||
//! Will construct this block from a hexstring
|
||||
void FromHexString(const std::string& str);
|
||||
|
||||
//! Will construct this block from a bytestring (any characters)
|
||||
void FromByteString(const std::string& str);
|
||||
|
||||
//! Will construct this block from a textstring (any length)
|
||||
void FromTextString(const std::string& str);
|
||||
|
||||
//! Will create a bitset-compatible string ("0101110..") representation
|
||||
//! of this block. Length will always be 512.
|
||||
std::string ToBinaryString() const;
|
||||
|
||||
//! Will create a hexstring representation of this block.
|
||||
std::string ToHexString() const;
|
||||
|
||||
//! Will create a bytestring representation of this block.
|
||||
std::string ToByteString() const;
|
||||
|
||||
//! Will create a textstring representation of this block.
|
||||
//! The difference to a bytestring is that it gets trimmed after a nullterminator.
|
||||
std::string ToTextString() const;
|
||||
|
||||
//! Will matrix-multiply two blocks together.
|
||||
//! Since the matrices values are pretty much sudo-random,
|
||||
//! they will most likely integer-overflow.
|
||||
//! So see this as a one-way function.
|
||||
[[nodiscard]] Basic_Block<T> MMul(const Basic_Block<T>& other) const;
|
||||
[[nodiscard]] Basic_Block<T> operator*(const Basic_Block<T>& other) const;
|
||||
|
||||
//! Will matrix-multiply two blocks together,
|
||||
//! and directly write into this same block.
|
||||
//! Since the matrices values are pretty much sudo-random,
|
||||
//! they will most likely integer-overflow.
|
||||
//! So see this as a one-way function.
|
||||
void MMulInplace(const Basic_Block<T>& other);
|
||||
Basic_Block<T>& operator*=(const Basic_Block<T>& other);
|
||||
|
||||
//! Will xor two blocks together
|
||||
[[nodiscard]] Basic_Block<T> Xor(const Basic_Block<T>& other) const;
|
||||
//! Will xor two blocks together
|
||||
[[nodiscard]] Basic_Block<T> operator^(const Basic_Block<T>& other) const;
|
||||
|
||||
//! Will xor two blocks together, inplace
|
||||
void XorInplace(const Basic_Block<T>& other);
|
||||
//! Will xor two blocks together, inplace
|
||||
Basic_Block<T>& operator^=(const Basic_Block<T>& other);
|
||||
|
||||
//! Will add all the integer making up this block, one by one
|
||||
[[nodiscard]] Basic_Block<T> Add(const Basic_Block<T>& other) const;
|
||||
//! Will add all the integer making up this block, one by one
|
||||
[[nodiscard]] Basic_Block<T> operator+(const Basic_Block<T>& other) const;
|
||||
|
||||
//! Will add all the integer making up this block, one by one, inplace
|
||||
void AddInplace(const Basic_Block<T>& other);
|
||||
//! Will add all the integer making up this block, one by one, inplace
|
||||
Basic_Block<T>& operator+=(const Basic_Block<T>& other);
|
||||
|
||||
//! Will subtract all the integer making up this block, one by one
|
||||
[[nodiscard]] Basic_Block<T> Sub(const Basic_Block<T>& other) const;
|
||||
//! Will subtract all the integer making up this block, one by one
|
||||
[[nodiscard]] Basic_Block<T> operator-(const Basic_Block<T>& other) const;
|
||||
|
||||
//! Will subtract all the integer making up this block, one by one, inplace
|
||||
void SubInplace(const Basic_Block<T>& other);
|
||||
//! Will subtract all the integer making up this block, one by one, inplace
|
||||
Basic_Block<T>& operator-=(const Basic_Block<T>& other);
|
||||
|
||||
//! Will shift rows upwards by 1
|
||||
[[nodiscard]] Basic_Block<T> ShiftRowsUp() const;
|
||||
|
||||
//! Will shift rows upwards by 1
|
||||
void ShiftRowsUpInplace();
|
||||
|
||||
//! Will shift matrix rows downwards by 1
|
||||
[[nodiscard]] Basic_Block<T> ShiftRowsDown() const;
|
||||
|
||||
//! Will shift matrix rows downwards by 1
|
||||
void ShiftRowsDownInplace();
|
||||
|
||||
//! Will shift matrix columns to the left by 1
|
||||
[[nodiscard]] Basic_Block<T> ShiftColumnsLeft() const;
|
||||
|
||||
//! Will shift matrix columns to the left by 1
|
||||
void ShiftColumnsLeftInplace();
|
||||
|
||||
//! Will shift matrix columns to the right by 1
|
||||
[[nodiscard]] Basic_Block<T> ShiftColumnsRight() const;
|
||||
|
||||
//! Will shift matrix columns to the right by 1
|
||||
void ShiftColumnsRightInplace();
|
||||
|
||||
//! Will shift array cells to the left by 1
|
||||
[[nodiscard]] Basic_Block<T> ShiftCellsLeft() const;
|
||||
|
||||
//! Will shift array cells to the left by 1
|
||||
void ShiftCellsLeftInplace();
|
||||
|
||||
//! Will shift array cells to the right by 1
|
||||
[[nodiscard]] Basic_Block<T> ShiftCellsRight() const;
|
||||
|
||||
//! Will shift array cells to the right by 1
|
||||
void ShiftCellsRightInplace();
|
||||
|
||||
//! Will copy a block
|
||||
Basic_Block<T>& operator=(const Basic_Block<T>& other);
|
||||
|
||||
//! Will compare whether or not two blocks are equal
|
||||
[[nodiscard]] bool operator==(const Basic_Block<T>& other) const;
|
||||
//! Will compare whether or not two blocks are unequal
|
||||
[[nodiscard]] bool operator!=(const Basic_Block<T>& other) const;
|
||||
|
||||
//! Will zero all data
|
||||
void Reset();
|
||||
|
||||
//! Will return the state of any given bit
|
||||
[[nodiscard]] bool GetBit(const std::size_t index) const;
|
||||
|
||||
//! Will set the state of any given bit
|
||||
void SetBit(const std::size_t index, const bool state);
|
||||
|
||||
//! Will flip the state of any given bit
|
||||
void FlipBit(const std::size_t index);
|
||||
|
||||
//! Will shift all bits to the left by 1
|
||||
[[nodiscard]] Basic_Block<T> ShiftBitsLeft() const;
|
||||
|
||||
//! Will shift all bits to the left by 1, inplace
|
||||
void ShiftBitsLeftInplace();
|
||||
|
||||
//! Will shift all bits to the right by 1
|
||||
[[nodiscard]] Basic_Block<T> ShiftBitsRight() const;
|
||||
|
||||
//! Will shift all bits to the right by 1, inplace
|
||||
void ShiftBitsRightInplace();
|
||||
|
||||
//! Returns 32-bit chunks of data, indexed by matrix coordinates (0-3)
|
||||
[[nodiscard]] T& Get(const std::uint8_t row, const std::uint8_t column);
|
||||
//! Returns 32-bit chunks of data, indexed by matrix coordinates (0-3)
|
||||
[[nodiscard]] const T& Get(const std::uint8_t row, const std::uint8_t column) const;
|
||||
|
||||
//! Returns 32-bit chunks of data, indexed by a 1d-index (0-16)
|
||||
[[nodiscard]] T& Get(const std::uint8_t index);
|
||||
|
||||
//! Returns 32-bit chunks of data, indexed by a 1d-index (0-16)
|
||||
[[nodiscard]] const T& Get(const std::uint8_t index) const;
|
||||
|
||||
//! Returns 32-bit chunks of data, indexed by a 1d-index (0-16)
|
||||
[[nodiscard]] T& operator[](const std::uint8_t index);
|
||||
|
||||
//! Returns 32-bit chunks of data, indexed by a 1d-index (0-16)
|
||||
[[nodiscard]] const T& operator[](const std::uint8_t index) const;
|
||||
|
||||
//! Will return a reference to the data array
|
||||
T* Data() noexcept;
|
||||
|
||||
//! Will return a reference to the data array
|
||||
const T* Data() const noexcept;
|
||||
|
||||
static constexpr std::size_t CHUNK_SIZE = sizeof(T);
|
||||
static constexpr std::size_t CHUNK_SIZE_BITS = CHUNK_SIZE * 8;
|
||||
static constexpr std::size_t BLOCK_SIZE = CHUNK_SIZE * 16;
|
||||
static constexpr std::size_t BLOCK_SIZE_BITS = CHUNK_SIZE_BITS * 16;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const Basic_Block<T>& b) {
|
||||
for (std::size_t i = 0; i < b.data.size(); i++) {
|
||||
os << std::bitset<Basic_Block<T>::CHUNK_SIZE_BITS>(b.data[i]).to_string();
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::array<T, 16> data;
|
||||
};
|
||||
|
||||
//! This a full-sized 512-bit block
|
||||
typedef Basic_Block<std::uint32_t> Block;
|
||||
|
||||
//! This is a half-block used within the feistel class
|
||||
typedef Basic_Block<std::uint16_t> Halfblock;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,12 +0,0 @@
|
||||
#ifndef GCRYPT_CONFIG_H
|
||||
#define GCRYPT_CONFIG_H
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
// MUST BE > 2
|
||||
constexpr std::size_t N_ROUNDS = 6;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,72 +0,0 @@
|
||||
#ifndef GCRYPT_FEISTEL_H
|
||||
#define GCRYPT_FEISTEL_H
|
||||
|
||||
#include "GCrypt/Keyset.h"
|
||||
#include "GCrypt/Block.h"
|
||||
#include "GCrypt/Key.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
/** Class to perform a feistel block chipher
|
||||
*/
|
||||
class Feistel {
|
||||
public:
|
||||
//! Empty initializer. If you use this, you must call SetKey()!
|
||||
Feistel();
|
||||
|
||||
//! Will initialize the feistel cipher with a key
|
||||
explicit Feistel(const Key& key);
|
||||
|
||||
Feistel(const Feistel& other) = delete;
|
||||
Feistel(Feistel&& other) noexcept = delete;
|
||||
|
||||
~Feistel();
|
||||
|
||||
//! Will set the seed-key for this feistel network.
|
||||
//! Roundkeys will be derived from this.
|
||||
void SetKey(const Key& key);
|
||||
|
||||
//! Will encipher a data block via the set seed-key
|
||||
Block Encipher(const Block& data);
|
||||
|
||||
//! Will decipher a data block via the set seed-key
|
||||
Block Decipher(const Block& data);
|
||||
|
||||
void operator=(const Feistel& other);
|
||||
|
||||
private:
|
||||
//! Will run the feistel rounds, with either regular key
|
||||
//! order or reversed key order
|
||||
Block Run(const Block& data, bool modeEncrypt);
|
||||
|
||||
//! Arbitrary cipher function
|
||||
static Halfblock F(Halfblock m, const Key& key);
|
||||
|
||||
//! Split a data block into two half blocks (into L and R)
|
||||
static std::pair<Halfblock, Halfblock> FeistelSplit(const Block& block);
|
||||
|
||||
//! Combine two half blocks (L and R) into a regular data block
|
||||
static Block FeistelCombine(const Halfblock& l, const Halfblock& r);
|
||||
|
||||
//! Will expand a halfblock to a fullblock
|
||||
static Block ExpansionFunction(const Halfblock& block);
|
||||
|
||||
//! Will reduce a fullblock to a halfblock
|
||||
static Halfblock ReductionFunction(const Block& block);
|
||||
|
||||
//! Substitutes eight bits by static random others, inplace
|
||||
static void SBox(Block& block);
|
||||
|
||||
//! Will generate a the round keys
|
||||
void GenerateRoundKeys(const Key& seedKey);
|
||||
|
||||
//! Will zero the memory used by the keyset
|
||||
void ZeroKeyMemory();
|
||||
|
||||
Keyset roundKeys;
|
||||
|
||||
bool isInitialized = false;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,54 +0,0 @@
|
||||
#ifndef GCRYPT_GCIPHER_H
|
||||
#define GCRYPT_GCIPHER_H
|
||||
|
||||
#include "GCrypt/Feistel.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
/** Class to apply a block/-stream cipher to messages of arbitrary length in a distributed manner
|
||||
*/
|
||||
class GCipher {
|
||||
public:
|
||||
//! Describes the direction the cipher runs in
|
||||
enum class DIRECTION {
|
||||
ENCIPHER,
|
||||
DECIPHER
|
||||
};
|
||||
|
||||
//! Empty initializer. If you use this, you must call Initialize()!
|
||||
GCipher();
|
||||
|
||||
//! Will initialize this cipher with a key
|
||||
explicit GCipher(const Key& key, const DIRECTION direction);
|
||||
|
||||
// Disable copying
|
||||
GCipher(const GCipher& other) = delete;
|
||||
GCipher(GCipher&& other) noexcept = delete;
|
||||
|
||||
//! Will digest a data block, and return it
|
||||
Block Digest(const Block& input);
|
||||
|
||||
//! Will update the base key used
|
||||
void SetKey(const Key& key);
|
||||
|
||||
void operator=(const GCipher& other);
|
||||
|
||||
|
||||
//! Will initialize the cipher with a key, and a mode.
|
||||
//! If called on an existing object, it will reset its state.
|
||||
void Initialize(const Key& key, const DIRECTION direction);
|
||||
|
||||
private:
|
||||
DIRECTION direction;
|
||||
|
||||
//! The feistel instance to be used
|
||||
Feistel feistel;
|
||||
|
||||
//! The last block, required for CBC.
|
||||
Block lastBlock;
|
||||
|
||||
bool isInitialized = false;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,45 +0,0 @@
|
||||
#ifndef GCRYPT_GHASH_H
|
||||
#define GCRYPT_GHASH_H
|
||||
|
||||
#include "GCrypt/Block.h"
|
||||
#include "GCrypt/GCipher.h"
|
||||
#include <vector>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
/** This class implements a hash function, based on the GCrypt cipher
|
||||
*/
|
||||
class GHash {
|
||||
public:
|
||||
GHash();
|
||||
|
||||
//! Will add the hash value of the block `data` to the hashsum.
|
||||
//! WARNING: If you compute hashes using this digestive method,
|
||||
//! you REALLY REALLY should add a trailing block just containing the cleartext size!
|
||||
//! You MOST LIKELY just want to use the wrapper function GHash::CalculateHashsum(Flexblock const&) instead!
|
||||
void Digest(const Block& data);
|
||||
|
||||
//! Will return the current hashsum
|
||||
const Block& GetHashsum() const;
|
||||
|
||||
//! Will calculate a hashsum for `blocks`.
|
||||
//! Whilst n_bytes is optional, it is HIGHLY recommended to supply.
|
||||
//! Without specifying the size of the input (doesn't always have to be 512*n bits)
|
||||
//! b'293eff' would hash to the exact same values as b'293eff0000'
|
||||
static Block CalculateHashsum(const std::vector<Block>& blocks, std::size_t n_bytes = std::string::npos);
|
||||
|
||||
//! Will calculate a hashsum for a string
|
||||
static Block HashString(const std::string& str);
|
||||
|
||||
void operator=(const GHash& other);
|
||||
|
||||
private:
|
||||
//! The cipher to use
|
||||
GCipher cipher;
|
||||
|
||||
//! The current state of the hashsum
|
||||
Block block;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,71 +0,0 @@
|
||||
#ifndef GCRYPT_GPRNG_H
|
||||
#define GCRYPT_GPRNG_H
|
||||
|
||||
#include "GCrypt/GHash.h"
|
||||
#include "GCrypt/Util.h"
|
||||
#include <string.h>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
/** This class implements a pseudo random number generator, based on the GCrypt hash function
|
||||
*/
|
||||
class GPrng {
|
||||
public:
|
||||
//! Will instanciate the prng with a seed. Seed could also be a GCrypt::Key.
|
||||
GPrng(const Block& seed);
|
||||
|
||||
//! Will instanciate the GPrng with no seed. You should really seed it later.
|
||||
GPrng();
|
||||
|
||||
//! Will reset and seed the prng. Seed could also be a GCrypt::Key.
|
||||
void Seed(const Block& seed);
|
||||
|
||||
//! Will return a random bit.
|
||||
bool GetBit();
|
||||
|
||||
//! Will return a randomized instance of any primitive.
|
||||
template <typename T>
|
||||
T GetRandom() {
|
||||
static_assert(std::is_fundamental<T>::value, "Leonetienne::GCrypt::GPrng::GetRandom() may only be used with primitive types!");
|
||||
|
||||
// Pull the required amount of bits
|
||||
std::stringstream ss;
|
||||
for (std::size_t i = 0; i < sizeof(T)*8; i++) {
|
||||
ss << (GetBit() ? '1' : '0');
|
||||
}
|
||||
|
||||
// Transform to bytes
|
||||
const std::string bits = ss.str();
|
||||
ss.str("");
|
||||
for (std::size_t i = 0; i < bits.size(); i += 8) {
|
||||
ss << (char)std::bitset<8>(bits.substr(i, 8)).to_ulong();
|
||||
}
|
||||
const std::string bytes = ss.str();
|
||||
|
||||
// Cram bytes into type
|
||||
T t;
|
||||
memcpy(&t, bytes.data(), sizeof(T));
|
||||
|
||||
// Return our randomized primitive
|
||||
return t;
|
||||
}
|
||||
|
||||
//! Will return a random unsigned 32-bit integer
|
||||
std::uint32_t operator()();
|
||||
|
||||
//! Will return a random block
|
||||
Block GetBlock();
|
||||
|
||||
private:
|
||||
//! Will generate the next block of random bits
|
||||
void AdvanceBlock();
|
||||
|
||||
GHash hasher;
|
||||
Block seed;
|
||||
std::size_t nextBit = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,45 +0,0 @@
|
||||
#ifndef GCRYPT_GWRAPPER_H
|
||||
#define GCRYPT_GWRAPPER_H
|
||||
|
||||
#include "GCrypt/Block.h"
|
||||
#include "GCrypt/GCipher.h"
|
||||
#include "GCrypt/Key.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
/** This class is a wrapper to make working with the GCipher
|
||||
* super easy with a python-like syntax
|
||||
*/
|
||||
class GWrapper {
|
||||
public:
|
||||
//! Will encrypt a string and return it hexadecimally encoded.
|
||||
static std::string EncryptString(const std::string& cleartext, const Key& key);
|
||||
|
||||
//! Will decrypt a hexadecimally encoded string.
|
||||
static std::string DecryptString(const std::string& ciphertext, const Key& key);
|
||||
|
||||
//! Will encrypt a file.
|
||||
//! Returns false if anything goes wrong (like, file-access).
|
||||
//! @filename_in The file to be read.
|
||||
//! @filename_out The file the encrypted version should be saved in.
|
||||
static bool EncryptFile(const std::string& filename_in, const std::string& filename_out, const Key& key, bool printProgressReport = false);
|
||||
|
||||
//! Will decrypt a file.
|
||||
//! Returns false if anything goes wrong (like, file-access).
|
||||
//! @filename_in The file to be read.
|
||||
//! @filename_out The file the decrypted version should be saved in.
|
||||
static bool DecryptFile(const std::string& filename_in, const std::string& filename_out, const Key& key, bool printProgressReport = false);
|
||||
|
||||
//! Will enncrypt or decrypt an entire flexblock of binary data, given a key.
|
||||
static std::vector<Block> CipherBlocks(const std::vector<Block>& data, const Key& key, const GCipher::DIRECTION direction);
|
||||
|
||||
private:
|
||||
|
||||
// No instanciation! >:(
|
||||
GWrapper();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include "GCrypt/Config.h"
|
||||
#include "GCrypt/Block.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
/** Will create a sudo-random Block based on a seed
|
||||
*/
|
||||
class InitializationVector {
|
||||
public:
|
||||
InitializationVector(const Block& seed);
|
||||
|
||||
operator Block() const;
|
||||
|
||||
private:
|
||||
Block iv;
|
||||
};
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
#ifndef GCRYPT_KEY_H
|
||||
#define GCRYPT_KEY_H
|
||||
#include "GCrypt/Block.h"
|
||||
#include <string>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
/** This class represents encryption keys.
|
||||
* You can copy them, create them from data blocks,
|
||||
* or even read from files.
|
||||
*/
|
||||
class Key : public Block {
|
||||
public:
|
||||
//! Will generate a key from a password
|
||||
static Key FromPassword(const std::string& password);
|
||||
|
||||
//! Will generate a random key from actual randomness (std::random_device)
|
||||
static Key Random();
|
||||
|
||||
//! Loads a keyfile
|
||||
static Key LoadFromFile(const std::string& path);
|
||||
|
||||
//! Will save a keyfile
|
||||
void WriteToFile(const std::string& path) const;
|
||||
|
||||
Key();
|
||||
Key(const Key& k);
|
||||
Key(const Block& b);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,13 +0,0 @@
|
||||
#ifndef GCRYPT_KEYSET_H
|
||||
#define GCRYPT_KEYSET_H
|
||||
|
||||
#include <array>
|
||||
#include "GCrypt/Key.h"
|
||||
#include "GCrypt/Config.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
typedef std::array<Key, N_ROUNDS> Keyset;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,46 +0,0 @@
|
||||
#ifndef GCRYPT_SBOX_LOOKUP
|
||||
#define GCRYPT_SBOX_LOOKUP
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
static const std::array<std::uint8_t, 256> sboxLookup {
|
||||
0x23,0xF7,0xA2,0x31,0x5B,0x0C,0x13,0xEE,
|
||||
0xF8,0x1B,0x0B,0xA9,0x37,0x9F,0x55,0xF3,
|
||||
0x7D,0x71,0x9E,0x89,0x38,0x53,0x3D,0xE9,
|
||||
0x47,0xA4,0x30,0xBF,0x82,0xE3,0x69,0x5C,
|
||||
0x3C,0x88,0xDE,0x7F,0x29,0xEB,0x5F,0x02,
|
||||
0x63,0x42,0xDC,0x36,0x20,0x6B,0x9C,0x4A,
|
||||
0xA8,0x11,0x6D,0x67,0x3A,0xF4,0x33,0x61,
|
||||
0x1C,0x4C,0x22,0x07,0x6F,0x80,0xA5,0x96,
|
||||
0x77,0x62,0xDD,0x6A,0x60,0x05,0x08,0x72,
|
||||
0xE5,0x1D,0x39,0xA7,0x58,0x3F,0x57,0xAD,
|
||||
0xFF,0x09,0xC5,0xB2,0xE7,0x94,0xEA,0x34,
|
||||
0x9A,0x5D,0x52,0xE2,0xAE,0x99,0xBB,0x44,
|
||||
0xFD,0x73,0xEC,0x87,0xED,0xBA,0x7C,0xF5,
|
||||
0xDA,0x01,0xC7,0xC1,0xB6,0x81,0x12,0xD5,
|
||||
0x7A,0x16,0x18,0x97,0x74,0x32,0xBD,0x56,
|
||||
0xFE,0x79,0x3E,0x95,0x93,0xAB,0x6C,0xC6,
|
||||
0x2A,0x27,0x19,0x26,0x2E,0x41,0x0F,0x85,
|
||||
0x66,0x59,0xEF,0x98,0x10,0xE8,0xE6,0x49,
|
||||
0xAC,0x0D,0x2D,0xD3,0xF0,0x92,0x8F,0xD9,
|
||||
0xAF,0xC8,0xB5,0xBC,0x6E,0xD6,0x78,0x8E,
|
||||
0x17,0xCB,0x75,0x50,0x51,0x84,0xB7,0x4D,
|
||||
0x70,0x9D,0x8A,0x2B,0x0E,0x35,0xB9,0x40,
|
||||
0x00,0x21,0xC3,0xB3,0x43,0xCD,0x65,0xC0,
|
||||
0x4E,0xCF,0xCA,0x28,0x45,0x46,0x54,0x8B,
|
||||
0x0A,0x5A,0x1F,0x24,0xFA,0xA6,0xB4,0xD7,
|
||||
0x3B,0xFC,0x5E,0xA3,0xB8,0x04,0xCE,0xF2,
|
||||
0xFB,0xD4,0x8C,0xE4,0x90,0xB1,0x06,0x8D,
|
||||
0x86,0xA1,0xE0,0x68,0xD1,0x2C,0x03,0x64,
|
||||
0x9B,0x4F,0x14,0x1E,0x7B,0x76,0x48,0xCC,
|
||||
0xC4,0x15,0xAA,0xC9,0xE1,0x91,0xF6,0xD0,
|
||||
0x25,0xA0,0x7E,0xB0,0x1A,0xBE,0xC2,0x4B,
|
||||
0xF1,0xD2,0xDF,0x2F,0xF9,0xDB,0xD8,0x83
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,44 +0,0 @@
|
||||
#ifndef GCRYPT_UTIL_H
|
||||
#define GCRYPT_UTIL_H
|
||||
|
||||
#include <bitset>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include "GCrypt/Block.h"
|
||||
#include "GCrypt/Config.h"
|
||||
#include "GCrypt/GCipher.h"
|
||||
#include "GCrypt/InitializationVector.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
//! Mod-operator that works with negative values
|
||||
inline int Mod(const int numerator, const int denominator) {
|
||||
return (denominator + (numerator % denominator)) % denominator;
|
||||
}
|
||||
|
||||
//! Will pad a string to a set length with a certain character
|
||||
std::string PadStringToLength(const std::string& str, const std::size_t len, const char pad, const bool padLeft = true);
|
||||
|
||||
//! Will convert a string to a vector of blocks
|
||||
std::vector<Block> StringToBitblocks(const std::string& str);
|
||||
|
||||
//! Will convert an array of data blocks to a bytestring
|
||||
std::string BitblocksToBytes(const std::vector<Block>& bits);
|
||||
|
||||
//! Will convert an array of blocks to a character-string
|
||||
//! The difference to BitblocksToBytes() is, that it strips excess nullbytes
|
||||
std::string BitblocksToString(const std::vector<Block>& blocks);
|
||||
|
||||
//! Will read a file directly to data blocks, and yield the amount of bytes read
|
||||
std::vector<Block> ReadFileToBlocks(const std::string& filepath, std::size_t& bytes_read);
|
||||
|
||||
//! Will read a file directly to data blocks
|
||||
std::vector<Block> ReadFileToBlocks(const std::string& filepath);
|
||||
|
||||
//! Will write data blocks directly to a file
|
||||
void WriteBlocksToFile(const std::string& filepath, const std::vector<Block>& blocks);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,7 +0,0 @@
|
||||
#ifndef GCRYPT_VERSION_H
|
||||
#define GCRYPT_VERSION_H
|
||||
|
||||
#define GCRYPT_VERSION 0.236
|
||||
|
||||
#endif
|
||||
|
@ -1,839 +0,0 @@
|
||||
#include "GCrypt/Block.h"
|
||||
#include "GCrypt/Config.h"
|
||||
#include "GCrypt/Util.h"
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
|
||||
// Just to be sure, the compiler will optimize this
|
||||
// little formula out, let's do it in the preprocessor
|
||||
namespace {
|
||||
constexpr std::size_t MAT_INDEX(const std::size_t row, const std::size_t column) {
|
||||
return column*4 + row;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T>::Basic_Block() {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T>::Basic_Block(const std::string& str) {
|
||||
FromBinaryString(str);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T>::Basic_Block(const Basic_Block<T>& other) {
|
||||
data = other.data;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::FromBinaryString(const std::string& str) {
|
||||
|
||||
if (str.length() != BLOCK_SIZE_BITS) {
|
||||
throw std::invalid_argument(
|
||||
std::string("Unable to read binary block: \"") + str + "\": Length is not BLOCK_SIZE_BITS."
|
||||
);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < data.size(); i++) {
|
||||
data[i] = std::bitset<CHUNK_SIZE_BITS>(
|
||||
str.substr(i*CHUNK_SIZE_BITS, CHUNK_SIZE_BITS)
|
||||
).to_ulong();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::FromHexString(const std::string& str) {
|
||||
|
||||
if (str.length() != BLOCK_SIZE*2) {
|
||||
throw std::invalid_argument(
|
||||
std::string("Unable to read hex block: \"") + str + "\": Length is not BLOCK_SIZE*2."
|
||||
);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < str.length(); i += CHUNK_SIZE*2) {
|
||||
const std::string hexChunk = str.substr(i, CHUNK_SIZE*2);
|
||||
try {
|
||||
data[i / (CHUNK_SIZE*2)] = std::stoul(hexChunk, NULL, 16);
|
||||
}
|
||||
catch (std::invalid_argument&) {
|
||||
throw std::invalid_argument(
|
||||
std::string("Unable to read hex block: \"") + hexChunk + "\"."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::FromByteString(const std::string& str) {
|
||||
|
||||
if (str.length() != BLOCK_SIZE) {
|
||||
throw std::invalid_argument(
|
||||
std::string("Unable to read byte block: \"") + str + "\": Length is not BLOCK_SIZE."
|
||||
);
|
||||
}
|
||||
|
||||
// Iterate over all bytes in the block
|
||||
std::uint8_t* curByte = (std::uint8_t*)(void*)Data();
|
||||
const char* strIt = 0;
|
||||
for (std::size_t i = 0; i < BLOCK_SIZE; i++) {
|
||||
*curByte++ = str[i];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::FromTextString(const std::string& str) {
|
||||
// Just pad the input string to lenght, and treat it as a byte string
|
||||
FromByteString(
|
||||
PadStringToLength(str, BLOCK_SIZE, '\0', false)
|
||||
);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string Basic_Block<T>::ToBinaryString() const {
|
||||
|
||||
std::stringstream ss;
|
||||
for (std::size_t i = 0; i < data.size(); i++) {
|
||||
ss << std::bitset<CHUNK_SIZE_BITS>(data[i]).to_string();
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string Basic_Block<T>::ToHexString() const {
|
||||
|
||||
std::stringstream ss;
|
||||
for (std::size_t i = 0; i < data.size(); i++) {
|
||||
ss
|
||||
<< std::setfill('0')
|
||||
<< std::setw(CHUNK_SIZE*2)
|
||||
<< std::hex
|
||||
<< data[i]
|
||||
;
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string Basic_Block<T>::ToByteString() const {
|
||||
|
||||
std::stringstream ss;
|
||||
ss.write((const char*)(void*)Data(), BLOCK_SIZE);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string Basic_Block<T>::ToTextString() const {
|
||||
|
||||
std::string bytes = ToByteString();
|
||||
|
||||
// Trim extra nullterminators
|
||||
bytes.resize(strlen(bytes.data()));
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::MMul(const Basic_Block<T>& o) const {
|
||||
|
||||
Basic_Block<T> m;
|
||||
|
||||
// Maybe pre-calculate the 1d-index...?
|
||||
|
||||
m.Get(MAT_INDEX(0, 0)) = (this->Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 0))) + (this->Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 0))) + (this->Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 0))) + (this->Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 0)));
|
||||
m.Get(MAT_INDEX(0, 1)) = (this->Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 1))) + (this->Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 1))) + (this->Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 1))) + (this->Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 1)));
|
||||
m.Get(MAT_INDEX(0, 2)) = (this->Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 2))) + (this->Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 2))) + (this->Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 2))) + (this->Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 2)));
|
||||
m.Get(MAT_INDEX(0, 3)) = (this->Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 3))) + (this->Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 3))) + (this->Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 3))) + (this->Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 3)));
|
||||
|
||||
m.Get(MAT_INDEX(1, 0)) = (this->Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 0))) + (this->Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 0))) + (this->Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 0))) + (this->Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 0)));
|
||||
m.Get(MAT_INDEX(1, 1)) = (this->Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 1))) + (this->Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 1))) + (this->Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 1))) + (this->Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 1)));
|
||||
m.Get(MAT_INDEX(1, 2)) = (this->Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 2))) + (this->Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 2))) + (this->Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 2))) + (this->Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 2)));
|
||||
m.Get(MAT_INDEX(1, 3)) = (this->Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 3))) + (this->Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 3))) + (this->Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 3))) + (this->Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 3)));
|
||||
|
||||
m.Get(MAT_INDEX(2, 0)) = (this->Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 0))) + (this->Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 0))) + (this->Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 0))) + (this->Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 0)));
|
||||
m.Get(MAT_INDEX(2, 1)) = (this->Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 1))) + (this->Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 1))) + (this->Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 1))) + (this->Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 1)));
|
||||
m.Get(MAT_INDEX(2, 2)) = (this->Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 2))) + (this->Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 2))) + (this->Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 2))) + (this->Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 2)));
|
||||
m.Get(MAT_INDEX(2, 3)) = (this->Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 3))) + (this->Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 3))) + (this->Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 3))) + (this->Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 3)));
|
||||
|
||||
m.Get(MAT_INDEX(3, 0)) = (this->Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 0))) + (this->Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 0))) + (this->Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 0))) + (this->Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 0)));
|
||||
m.Get(MAT_INDEX(3, 1)) = (this->Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 1))) + (this->Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 1))) + (this->Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 1))) + (this->Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 1)));
|
||||
m.Get(MAT_INDEX(3, 2)) = (this->Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 2))) + (this->Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 2))) + (this->Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 2))) + (this->Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 2)));
|
||||
m.Get(MAT_INDEX(3, 3)) = (this->Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 3))) + (this->Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 3))) + (this->Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 3))) + (this->Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 3)));
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::operator*(const Basic_Block<T>& other) const {
|
||||
return this->MMul(other);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::MMulInplace(const Basic_Block<T>& o) {
|
||||
|
||||
Basic_Block<T> m = *this;
|
||||
|
||||
// Maybe pre-calculate the 1d-index...?
|
||||
|
||||
this->Get(MAT_INDEX(0, 0)) = (m.Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 0))) + (m.Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 0))) + (m.Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 0))) + (m.Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 0)));
|
||||
this->Get(MAT_INDEX(0, 1)) = (m.Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 1))) + (m.Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 1))) + (m.Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 1))) + (m.Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 1)));
|
||||
this->Get(MAT_INDEX(0, 2)) = (m.Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 2))) + (m.Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 2))) + (m.Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 2))) + (m.Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 2)));
|
||||
this->Get(MAT_INDEX(0, 3)) = (m.Get(MAT_INDEX(0, 0)) * o.Get(MAT_INDEX(0, 3))) + (m.Get(MAT_INDEX(0, 1)) * o.Get(MAT_INDEX(1, 3))) + (m.Get(MAT_INDEX(0, 2)) * o.Get(MAT_INDEX(2, 3))) + (m.Get(MAT_INDEX(0, 3)) * o.Get(MAT_INDEX(3, 3)));
|
||||
|
||||
this->Get(MAT_INDEX(1, 0)) = (m.Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 0))) + (m.Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 0))) + (m.Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 0))) + (m.Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 0)));
|
||||
this->Get(MAT_INDEX(1, 1)) = (m.Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 1))) + (m.Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 1))) + (m.Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 1))) + (m.Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 1)));
|
||||
this->Get(MAT_INDEX(1, 2)) = (m.Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 2))) + (m.Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 2))) + (m.Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 2))) + (m.Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 2)));
|
||||
this->Get(MAT_INDEX(1, 3)) = (m.Get(MAT_INDEX(1, 0)) * o.Get(MAT_INDEX(0, 3))) + (m.Get(MAT_INDEX(1, 1)) * o.Get(MAT_INDEX(1, 3))) + (m.Get(MAT_INDEX(1, 2)) * o.Get(MAT_INDEX(2, 3))) + (m.Get(MAT_INDEX(1, 3)) * o.Get(MAT_INDEX(3, 3)));
|
||||
|
||||
this->Get(MAT_INDEX(2, 0)) = (m.Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 0))) + (m.Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 0))) + (m.Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 0))) + (m.Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 0)));
|
||||
this->Get(MAT_INDEX(2, 1)) = (m.Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 1))) + (m.Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 1))) + (m.Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 1))) + (m.Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 1)));
|
||||
this->Get(MAT_INDEX(2, 2)) = (m.Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 2))) + (m.Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 2))) + (m.Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 2))) + (m.Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 2)));
|
||||
this->Get(MAT_INDEX(2, 3)) = (m.Get(MAT_INDEX(2, 0)) * o.Get(MAT_INDEX(0, 3))) + (m.Get(MAT_INDEX(2, 1)) * o.Get(MAT_INDEX(1, 3))) + (m.Get(MAT_INDEX(2, 2)) * o.Get(MAT_INDEX(2, 3))) + (m.Get(MAT_INDEX(2, 3)) * o.Get(MAT_INDEX(3, 3)));
|
||||
|
||||
this->Get(MAT_INDEX(3, 0)) = (m.Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 0))) + (m.Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 0))) + (m.Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 0))) + (m.Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 0)));
|
||||
this->Get(MAT_INDEX(3, 1)) = (m.Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 1))) + (m.Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 1))) + (m.Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 1))) + (m.Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 1)));
|
||||
this->Get(MAT_INDEX(3, 2)) = (m.Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 2))) + (m.Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 2))) + (m.Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 2))) + (m.Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 2)));
|
||||
this->Get(MAT_INDEX(3, 3)) = (m.Get(MAT_INDEX(3, 0)) * o.Get(MAT_INDEX(0, 3))) + (m.Get(MAT_INDEX(3, 1)) * o.Get(MAT_INDEX(1, 3))) + (m.Get(MAT_INDEX(3, 2)) * o.Get(MAT_INDEX(2, 3))) + (m.Get(MAT_INDEX(3, 3)) * o.Get(MAT_INDEX(3, 3)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T>& Basic_Block<T>::operator*=(const Basic_Block<T>& other) {
|
||||
MMulInplace(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::Xor(const Basic_Block<T>& other) const {
|
||||
|
||||
Basic_Block<T> m;
|
||||
for (std::size_t i = 0; i < data.size(); i++) {
|
||||
m.Get(i) = this->Get(i) ^ other.Get(i);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::operator^(const Basic_Block<T>& other) const {
|
||||
return Xor(other);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::XorInplace(const Basic_Block<T>& other) {
|
||||
for (std::size_t i = 0; i < data.size(); i++) {
|
||||
this->Get(i) ^= other.Get(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T>& Basic_Block<T>::operator^=(const Basic_Block<T>& other) {
|
||||
XorInplace(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::Add(const Basic_Block<T>& other) const {
|
||||
|
||||
Basic_Block<T> m;
|
||||
for (std::size_t i = 0; i < data.size(); i++) {
|
||||
m.Get(i) = this->Get(i) + other.Get(i);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::operator+(const Basic_Block<T>& other) const {
|
||||
return Add(other);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::AddInplace(const Basic_Block<T>& other) {
|
||||
for (std::size_t i = 0; i < data.size(); i++) {
|
||||
this->Get(i) += other.Get(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T>& Basic_Block<T>::operator+=(const Basic_Block<T>& other) {
|
||||
AddInplace(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::Sub(const Basic_Block<T>& other) const {
|
||||
|
||||
Basic_Block<T> m;
|
||||
for (std::size_t i = 0; i < data.size(); i++) {
|
||||
m.Get(i) = this->Get(i) - other.Get(i);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::operator-(const Basic_Block<T>& other) const {
|
||||
return Sub(other);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::SubInplace(const Basic_Block<T>& other) {
|
||||
for (std::size_t i = 0; i < data.size(); i++) {
|
||||
this->Get(i) -= other.Get(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T>& Basic_Block<T>::operator-=(const Basic_Block<T>& other) {
|
||||
SubInplace(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::ShiftRowsUpInplace() {
|
||||
Basic_Block<T> tmp = *this;
|
||||
|
||||
Get(MAT_INDEX(0, 0)) = tmp.Get(MAT_INDEX(1, 0));
|
||||
Get(MAT_INDEX(0, 1)) = tmp.Get(MAT_INDEX(1, 1));
|
||||
Get(MAT_INDEX(0, 2)) = tmp.Get(MAT_INDEX(1, 2));
|
||||
Get(MAT_INDEX(0, 3)) = tmp.Get(MAT_INDEX(1, 3));
|
||||
|
||||
Get(MAT_INDEX(1, 0)) = tmp.Get(MAT_INDEX(2, 0));
|
||||
Get(MAT_INDEX(1, 1)) = tmp.Get(MAT_INDEX(2, 1));
|
||||
Get(MAT_INDEX(1, 2)) = tmp.Get(MAT_INDEX(2, 2));
|
||||
Get(MAT_INDEX(1, 3)) = tmp.Get(MAT_INDEX(2, 3));
|
||||
|
||||
Get(MAT_INDEX(2, 0)) = tmp.Get(MAT_INDEX(3, 0));
|
||||
Get(MAT_INDEX(2, 1)) = tmp.Get(MAT_INDEX(3, 1));
|
||||
Get(MAT_INDEX(2, 2)) = tmp.Get(MAT_INDEX(3, 2));
|
||||
Get(MAT_INDEX(2, 3)) = tmp.Get(MAT_INDEX(3, 3));
|
||||
|
||||
Get(MAT_INDEX(3, 0)) = tmp.Get(MAT_INDEX(0, 0));
|
||||
Get(MAT_INDEX(3, 1)) = tmp.Get(MAT_INDEX(0, 1));
|
||||
Get(MAT_INDEX(3, 2)) = tmp.Get(MAT_INDEX(0, 2));
|
||||
Get(MAT_INDEX(3, 3)) = tmp.Get(MAT_INDEX(0, 3));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::ShiftRowsUp() const {
|
||||
Basic_Block<T> b;
|
||||
|
||||
b.Get(MAT_INDEX(0, 0)) = Get(MAT_INDEX(1, 0));
|
||||
b.Get(MAT_INDEX(0, 1)) = Get(MAT_INDEX(1, 1));
|
||||
b.Get(MAT_INDEX(0, 2)) = Get(MAT_INDEX(1, 2));
|
||||
b.Get(MAT_INDEX(0, 3)) = Get(MAT_INDEX(1, 3));
|
||||
|
||||
b.Get(MAT_INDEX(1, 0)) = Get(MAT_INDEX(2, 0));
|
||||
b.Get(MAT_INDEX(1, 1)) = Get(MAT_INDEX(2, 1));
|
||||
b.Get(MAT_INDEX(1, 2)) = Get(MAT_INDEX(2, 2));
|
||||
b.Get(MAT_INDEX(1, 3)) = Get(MAT_INDEX(2, 3));
|
||||
|
||||
b.Get(MAT_INDEX(2, 0)) = Get(MAT_INDEX(3, 0));
|
||||
b.Get(MAT_INDEX(2, 1)) = Get(MAT_INDEX(3, 1));
|
||||
b.Get(MAT_INDEX(2, 2)) = Get(MAT_INDEX(3, 2));
|
||||
b.Get(MAT_INDEX(2, 3)) = Get(MAT_INDEX(3, 3));
|
||||
|
||||
b.Get(MAT_INDEX(3, 0)) = Get(MAT_INDEX(0, 0));
|
||||
b.Get(MAT_INDEX(3, 1)) = Get(MAT_INDEX(0, 1));
|
||||
b.Get(MAT_INDEX(3, 2)) = Get(MAT_INDEX(0, 2));
|
||||
b.Get(MAT_INDEX(3, 3)) = Get(MAT_INDEX(0, 3));
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::ShiftRowsDownInplace() {
|
||||
Basic_Block<T> tmp = *this;
|
||||
|
||||
Get(MAT_INDEX(0, 0)) = tmp.Get(MAT_INDEX(3, 0));
|
||||
Get(MAT_INDEX(0, 1)) = tmp.Get(MAT_INDEX(3, 1));
|
||||
Get(MAT_INDEX(0, 2)) = tmp.Get(MAT_INDEX(3, 2));
|
||||
Get(MAT_INDEX(0, 3)) = tmp.Get(MAT_INDEX(3, 3));
|
||||
|
||||
Get(MAT_INDEX(1, 0)) = tmp.Get(MAT_INDEX(0, 0));
|
||||
Get(MAT_INDEX(1, 1)) = tmp.Get(MAT_INDEX(0, 1));
|
||||
Get(MAT_INDEX(1, 2)) = tmp.Get(MAT_INDEX(0, 2));
|
||||
Get(MAT_INDEX(1, 3)) = tmp.Get(MAT_INDEX(0, 3));
|
||||
|
||||
Get(MAT_INDEX(2, 0)) = tmp.Get(MAT_INDEX(1, 0));
|
||||
Get(MAT_INDEX(2, 1)) = tmp.Get(MAT_INDEX(1, 1));
|
||||
Get(MAT_INDEX(2, 2)) = tmp.Get(MAT_INDEX(1, 2));
|
||||
Get(MAT_INDEX(2, 3)) = tmp.Get(MAT_INDEX(1, 3));
|
||||
|
||||
Get(MAT_INDEX(3, 0)) = tmp.Get(MAT_INDEX(2, 0));
|
||||
Get(MAT_INDEX(3, 1)) = tmp.Get(MAT_INDEX(2, 1));
|
||||
Get(MAT_INDEX(3, 2)) = tmp.Get(MAT_INDEX(2, 2));
|
||||
Get(MAT_INDEX(3, 3)) = tmp.Get(MAT_INDEX(2, 3));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::ShiftRowsDown() const {
|
||||
Basic_Block<T> b;
|
||||
|
||||
b.Get(MAT_INDEX(0, 0)) = Get(MAT_INDEX(3, 0));
|
||||
b.Get(MAT_INDEX(0, 1)) = Get(MAT_INDEX(3, 1));
|
||||
b.Get(MAT_INDEX(0, 2)) = Get(MAT_INDEX(3, 2));
|
||||
b.Get(MAT_INDEX(0, 3)) = Get(MAT_INDEX(3, 3));
|
||||
|
||||
b.Get(MAT_INDEX(1, 0)) = Get(MAT_INDEX(0, 0));
|
||||
b.Get(MAT_INDEX(1, 1)) = Get(MAT_INDEX(0, 1));
|
||||
b.Get(MAT_INDEX(1, 2)) = Get(MAT_INDEX(0, 2));
|
||||
b.Get(MAT_INDEX(1, 3)) = Get(MAT_INDEX(0, 3));
|
||||
|
||||
b.Get(MAT_INDEX(2, 0)) = Get(MAT_INDEX(1, 0));
|
||||
b.Get(MAT_INDEX(2, 1)) = Get(MAT_INDEX(1, 1));
|
||||
b.Get(MAT_INDEX(2, 2)) = Get(MAT_INDEX(1, 2));
|
||||
b.Get(MAT_INDEX(2, 3)) = Get(MAT_INDEX(1, 3));
|
||||
|
||||
b.Get(MAT_INDEX(3, 0)) = Get(MAT_INDEX(2, 0));
|
||||
b.Get(MAT_INDEX(3, 1)) = Get(MAT_INDEX(2, 1));
|
||||
b.Get(MAT_INDEX(3, 2)) = Get(MAT_INDEX(2, 2));
|
||||
b.Get(MAT_INDEX(3, 3)) = Get(MAT_INDEX(2, 3));
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::ShiftColumnsLeftInplace() {
|
||||
Basic_Block<T> tmp = *this;
|
||||
|
||||
Get(MAT_INDEX(0, 0)) = tmp.Get(MAT_INDEX(0, 1));
|
||||
Get(MAT_INDEX(1, 0)) = tmp.Get(MAT_INDEX(1, 1));
|
||||
Get(MAT_INDEX(2, 0)) = tmp.Get(MAT_INDEX(2, 1));
|
||||
Get(MAT_INDEX(3, 0)) = tmp.Get(MAT_INDEX(3, 1));
|
||||
|
||||
Get(MAT_INDEX(0, 1)) = tmp.Get(MAT_INDEX(0, 2));
|
||||
Get(MAT_INDEX(1, 1)) = tmp.Get(MAT_INDEX(1, 2));
|
||||
Get(MAT_INDEX(2, 1)) = tmp.Get(MAT_INDEX(2, 2));
|
||||
Get(MAT_INDEX(3, 1)) = tmp.Get(MAT_INDEX(3, 2));
|
||||
|
||||
Get(MAT_INDEX(0, 2)) = tmp.Get(MAT_INDEX(0, 3));
|
||||
Get(MAT_INDEX(1, 2)) = tmp.Get(MAT_INDEX(1, 3));
|
||||
Get(MAT_INDEX(2, 2)) = tmp.Get(MAT_INDEX(2, 3));
|
||||
Get(MAT_INDEX(3, 2)) = tmp.Get(MAT_INDEX(3, 3));
|
||||
|
||||
Get(MAT_INDEX(0, 3)) = tmp.Get(MAT_INDEX(0, 0));
|
||||
Get(MAT_INDEX(1, 3)) = tmp.Get(MAT_INDEX(1, 0));
|
||||
Get(MAT_INDEX(2, 3)) = tmp.Get(MAT_INDEX(2, 0));
|
||||
Get(MAT_INDEX(3, 3)) = tmp.Get(MAT_INDEX(3, 0));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::ShiftColumnsLeft() const {
|
||||
Basic_Block<T> b;
|
||||
|
||||
b.Get(MAT_INDEX(0, 0)) = Get(MAT_INDEX(0, 1));
|
||||
b.Get(MAT_INDEX(1, 0)) = Get(MAT_INDEX(1, 1));
|
||||
b.Get(MAT_INDEX(2, 0)) = Get(MAT_INDEX(2, 1));
|
||||
b.Get(MAT_INDEX(3, 0)) = Get(MAT_INDEX(3, 1));
|
||||
|
||||
b.Get(MAT_INDEX(0, 1)) = Get(MAT_INDEX(0, 2));
|
||||
b.Get(MAT_INDEX(1, 1)) = Get(MAT_INDEX(1, 2));
|
||||
b.Get(MAT_INDEX(2, 1)) = Get(MAT_INDEX(2, 2));
|
||||
b.Get(MAT_INDEX(3, 1)) = Get(MAT_INDEX(3, 2));
|
||||
|
||||
b.Get(MAT_INDEX(0, 2)) = Get(MAT_INDEX(0, 3));
|
||||
b.Get(MAT_INDEX(1, 2)) = Get(MAT_INDEX(1, 3));
|
||||
b.Get(MAT_INDEX(2, 2)) = Get(MAT_INDEX(2, 3));
|
||||
b.Get(MAT_INDEX(3, 2)) = Get(MAT_INDEX(3, 3));
|
||||
|
||||
b.Get(MAT_INDEX(0, 3)) = Get(MAT_INDEX(0, 0));
|
||||
b.Get(MAT_INDEX(1, 3)) = Get(MAT_INDEX(1, 0));
|
||||
b.Get(MAT_INDEX(2, 3)) = Get(MAT_INDEX(2, 0));
|
||||
b.Get(MAT_INDEX(3, 3)) = Get(MAT_INDEX(3, 0));
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::ShiftColumnsRightInplace() {
|
||||
Basic_Block<T> tmp = *this;
|
||||
|
||||
Get(MAT_INDEX(0, 1)) = tmp.Get(MAT_INDEX(0, 0));
|
||||
Get(MAT_INDEX(1, 1)) = tmp.Get(MAT_INDEX(1, 0));
|
||||
Get(MAT_INDEX(2, 1)) = tmp.Get(MAT_INDEX(2, 0));
|
||||
Get(MAT_INDEX(3, 1)) = tmp.Get(MAT_INDEX(3, 0));
|
||||
|
||||
Get(MAT_INDEX(0, 2)) = tmp.Get(MAT_INDEX(0, 1));
|
||||
Get(MAT_INDEX(1, 2)) = tmp.Get(MAT_INDEX(1, 1));
|
||||
Get(MAT_INDEX(2, 2)) = tmp.Get(MAT_INDEX(2, 1));
|
||||
Get(MAT_INDEX(3, 2)) = tmp.Get(MAT_INDEX(3, 1));
|
||||
|
||||
Get(MAT_INDEX(0, 3)) = tmp.Get(MAT_INDEX(0, 2));
|
||||
Get(MAT_INDEX(1, 3)) = tmp.Get(MAT_INDEX(1, 2));
|
||||
Get(MAT_INDEX(2, 3)) = tmp.Get(MAT_INDEX(2, 2));
|
||||
Get(MAT_INDEX(3, 3)) = tmp.Get(MAT_INDEX(3, 2));
|
||||
|
||||
Get(MAT_INDEX(0, 0)) = tmp.Get(MAT_INDEX(0, 3));
|
||||
Get(MAT_INDEX(1, 0)) = tmp.Get(MAT_INDEX(1, 3));
|
||||
Get(MAT_INDEX(2, 0)) = tmp.Get(MAT_INDEX(2, 3));
|
||||
Get(MAT_INDEX(3, 0)) = tmp.Get(MAT_INDEX(3, 3));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::ShiftColumnsRight() const {
|
||||
Basic_Block<T> b;
|
||||
|
||||
b.Get(MAT_INDEX(0, 1)) = Get(MAT_INDEX(0, 0));
|
||||
b.Get(MAT_INDEX(1, 1)) = Get(MAT_INDEX(1, 0));
|
||||
b.Get(MAT_INDEX(2, 1)) = Get(MAT_INDEX(2, 0));
|
||||
b.Get(MAT_INDEX(3, 1)) = Get(MAT_INDEX(3, 0));
|
||||
|
||||
b.Get(MAT_INDEX(0, 2)) = Get(MAT_INDEX(0, 1));
|
||||
b.Get(MAT_INDEX(1, 2)) = Get(MAT_INDEX(1, 1));
|
||||
b.Get(MAT_INDEX(2, 2)) = Get(MAT_INDEX(2, 1));
|
||||
b.Get(MAT_INDEX(3, 2)) = Get(MAT_INDEX(3, 1));
|
||||
|
||||
b.Get(MAT_INDEX(0, 3)) = Get(MAT_INDEX(0, 2));
|
||||
b.Get(MAT_INDEX(1, 3)) = Get(MAT_INDEX(1, 2));
|
||||
b.Get(MAT_INDEX(2, 3)) = Get(MAT_INDEX(2, 2));
|
||||
b.Get(MAT_INDEX(3, 3)) = Get(MAT_INDEX(3, 2));
|
||||
|
||||
b.Get(MAT_INDEX(0, 0)) = Get(MAT_INDEX(0, 3));
|
||||
b.Get(MAT_INDEX(1, 0)) = Get(MAT_INDEX(1, 3));
|
||||
b.Get(MAT_INDEX(2, 0)) = Get(MAT_INDEX(2, 3));
|
||||
b.Get(MAT_INDEX(3, 0)) = Get(MAT_INDEX(3, 3));
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::ShiftCellsLeftInplace() {
|
||||
Basic_Block<T> tmp = *this;
|
||||
|
||||
Get(15) = tmp.Get(0);
|
||||
|
||||
for (std::size_t i = 0; i < 15; i++) {
|
||||
Get(i) = tmp.Get(i+1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::ShiftCellsLeft() const {
|
||||
Basic_Block<T> b;
|
||||
|
||||
b.Get(15) = Get(0);
|
||||
|
||||
for (std::size_t i = 0; i < 15; i++) {
|
||||
b.Get(i) = Get(i+1);
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::ShiftCellsRightInplace() {
|
||||
Basic_Block<T> tmp = *this;
|
||||
|
||||
Get(0) = tmp.Get(15);
|
||||
|
||||
for (std::size_t i = 1; i < 16; i++) {
|
||||
Get(i) = tmp.Get(i-1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::ShiftCellsRight() const {
|
||||
Basic_Block<T> b;
|
||||
|
||||
b.Get(0) = Get(15);
|
||||
|
||||
for (std::size_t i = 1; i < 16; i++) {
|
||||
b.Get(i) = Get(i-1);
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T>& Basic_Block<T>::operator=(const Basic_Block<T>& other) {
|
||||
data = other.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Basic_Block<T>::GetBit(const std::size_t index) const {
|
||||
// Fetch index of integer the bit is located in
|
||||
const std::size_t intIndex = index / CHUNK_SIZE_BITS;
|
||||
|
||||
// Fetch bit index relative to that int
|
||||
const std::size_t relBitIndex = index - (intIndex * CHUNK_SIZE_BITS);
|
||||
|
||||
// Pre-calculate the bitmask to use
|
||||
const std::size_t bitmask = 1 << (CHUNK_SIZE_BITS - relBitIndex - 1);
|
||||
|
||||
return data[intIndex] & bitmask;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::SetBit(const std::size_t index, const bool state) {
|
||||
// Fetch index of integer the bit is located in
|
||||
const std::size_t intIndex = index / CHUNK_SIZE_BITS;
|
||||
|
||||
// Fetch bit index relative to that int
|
||||
const std::size_t relBitIndex = index - (intIndex * CHUNK_SIZE_BITS);
|
||||
|
||||
// Pre-calculate the bitmask to use
|
||||
const std::size_t bitmask = 1 << (CHUNK_SIZE_BITS - relBitIndex - 1);
|
||||
|
||||
// Set the bit
|
||||
if (state) {
|
||||
data[intIndex] |= bitmask;
|
||||
}
|
||||
// Clear the bit
|
||||
else {
|
||||
data[intIndex] &= ~bitmask;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::FlipBit(const std::size_t index) {
|
||||
// Fetch index of integer the bit is located in
|
||||
const std::size_t intIndex = index / CHUNK_SIZE_BITS;
|
||||
|
||||
// Fetch bit index relative to that int
|
||||
const std::size_t relBitIndex = index - (intIndex * CHUNK_SIZE_BITS);
|
||||
|
||||
// Pre-calculate the bitmask to use
|
||||
const std::size_t bitmask = 1 << (CHUNK_SIZE_BITS - relBitIndex - 1);
|
||||
|
||||
data[intIndex] ^= bitmask;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::ShiftBitsLeft() const {
|
||||
Basic_Block<T> b;
|
||||
|
||||
// First, copy this block over
|
||||
b = *this;
|
||||
|
||||
// Then, shift all integers individually
|
||||
for (std::size_t i = 0; i < data.size(); i++) {
|
||||
b.data[i] <<= 1;
|
||||
}
|
||||
|
||||
// Current state: the LSB is zero everywhere. We have to carry
|
||||
// it over manually from the previous state.
|
||||
|
||||
// Carry over the MSB of data[i] to LSB of data[i-1]
|
||||
constexpr std::size_t bitmaskMsb = 1 << (CHUNK_SIZE_BITS - 1);
|
||||
constexpr std::size_t bitmaskLsb = 1;
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
const bool msb = data[i] & bitmaskMsb;
|
||||
|
||||
// Set the lsb
|
||||
if (msb) {
|
||||
b.data[Mod(i-1, data.size())] |= bitmaskLsb;
|
||||
}
|
||||
// Clear the lsb
|
||||
else {
|
||||
b.data[Mod(i-1, data.size())] &= ~bitmaskLsb;
|
||||
}
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::ShiftBitsLeftInplace() {
|
||||
Basic_Block<T> tmp = *this;
|
||||
|
||||
// Then, shift all integers individually
|
||||
for (std::size_t i = 0; i < data.size(); i++) {
|
||||
data[i] <<= 1;
|
||||
}
|
||||
|
||||
// Current state: the LSB is zero everywhere. We have to carry
|
||||
// it over manually from the previous state.
|
||||
|
||||
// Carry over the MSB of data[i] to LSB of data[i-1]
|
||||
constexpr std::size_t bitmaskMsb = 1 << (CHUNK_SIZE_BITS - 1);
|
||||
constexpr std::size_t bitmaskLsb = 1;
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
const bool msb = tmp.data[i] & bitmaskMsb;
|
||||
|
||||
// Set the lsb
|
||||
if (msb) {
|
||||
data[Mod(i-1, data.size())] |= bitmaskLsb;
|
||||
}
|
||||
// Clear the lsb
|
||||
else {
|
||||
data[Mod(i-1, data.size())] &= ~bitmaskLsb;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Basic_Block<T> Basic_Block<T>::ShiftBitsRight() const {
|
||||
Basic_Block<T> b;
|
||||
|
||||
// First, copy this block over
|
||||
b = *this;
|
||||
|
||||
// Then, shift all integers individually
|
||||
for (std::size_t i = 0; i < data.size(); i++) {
|
||||
b.data[i] >>= 1;
|
||||
}
|
||||
|
||||
// Current state: the LSB is zero everywhere. We have to carry
|
||||
// it over manually from the previous state.
|
||||
|
||||
// Carry over the LSB of data[i] to MSB of data[i+1]
|
||||
constexpr std::size_t bitmaskMsb = 1 << (CHUNK_SIZE_BITS - 1);
|
||||
constexpr std::size_t bitmaskLsb = 1;
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
const bool lsb = data[i] & bitmaskLsb;
|
||||
|
||||
// Set the msb
|
||||
if (lsb) {
|
||||
b.data[Mod(i+1, data.size())] |= bitmaskMsb;
|
||||
}
|
||||
// Clear the msb
|
||||
else {
|
||||
b.data[Mod(i+1, data.size())] &= ~bitmaskMsb;
|
||||
}
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::ShiftBitsRightInplace() {
|
||||
Basic_Block<T> tmp = *this;
|
||||
|
||||
// Then, shift all integers individually
|
||||
for (std::size_t i = 0; i < data.size(); i++) {
|
||||
data[i] >>= 1;
|
||||
}
|
||||
|
||||
// Current state: the LSB is zero everywhere. We have to carry
|
||||
// it over manually from the previous state.
|
||||
|
||||
// Carry over the LSB of data[i] to MSB of data[i+1]
|
||||
constexpr std::size_t bitmaskMsb = 1 << (CHUNK_SIZE_BITS - 1);
|
||||
constexpr std::size_t bitmaskLsb = 1;
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
const bool lsb = tmp.data[i] & bitmaskLsb;
|
||||
|
||||
// Set the msb
|
||||
if (lsb) {
|
||||
data[Mod(i+1, data.size())] |= bitmaskMsb;
|
||||
}
|
||||
// Clear the msb
|
||||
else {
|
||||
data[Mod(i+1, data.size())] &= ~bitmaskMsb;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T& Basic_Block<T>::Get(const std::uint8_t row, const std::uint8_t column){
|
||||
return data[MAT_INDEX(row, column)];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T& Basic_Block<T>::Get(const std::uint8_t row, const std::uint8_t column) const {
|
||||
return data[MAT_INDEX(row, column)];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T& Basic_Block<T>::Get(const std::uint8_t index) {
|
||||
return data[index];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T& Basic_Block<T>::Get(const std::uint8_t index) const {
|
||||
return data[index];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T& Basic_Block<T>::operator[](const std::uint8_t index) {
|
||||
return data[index];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T& Basic_Block<T>::operator[](const std::uint8_t index) const {
|
||||
return data[index];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* Basic_Block<T>::Data() noexcept {
|
||||
return data.data();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T* Basic_Block<T>::Data() const noexcept {
|
||||
return data.data();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Basic_Block<T>::operator==(const Basic_Block<T>& other) const {
|
||||
return data == other.data;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Basic_Block<T>::operator!=(const Basic_Block<T>& other) const {
|
||||
return data != other.data;
|
||||
}
|
||||
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
#pragma optimize("", off )
|
||||
#elif defined __GNUG__
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("O0")
|
||||
#endif
|
||||
template <typename T>
|
||||
Basic_Block<T>::~Basic_Block() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Basic_Block<T>::Reset() {
|
||||
memset(data.data(), 0, CHUNK_SIZE*data.size());
|
||||
return;
|
||||
}
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
#pragma optimize("", on )
|
||||
#elif defined __GNUG__
|
||||
#pragma GCC pop_options
|
||||
#endif
|
||||
|
||||
// Instantiate templates
|
||||
template class Basic_Block<std::uint32_t>;
|
||||
template class Basic_Block<std::uint16_t>;
|
||||
}
|
||||
|
@ -1,278 +0,0 @@
|
||||
#include <unordered_map>
|
||||
#include "GCrypt/Feistel.h"
|
||||
#include "GCrypt/Util.h"
|
||||
#include "GCrypt/Config.h"
|
||||
#include "GCrypt/SBoxLookup.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
Feistel::Feistel() {
|
||||
}
|
||||
|
||||
Feistel::Feistel(const Key& key) {
|
||||
SetKey(key);
|
||||
}
|
||||
|
||||
Feistel::~Feistel() {
|
||||
ZeroKeyMemory();
|
||||
}
|
||||
|
||||
void Feistel::SetKey(const Key& key) {
|
||||
GenerateRoundKeys(key);
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
Block Feistel::Encipher(const Block& data) {
|
||||
return Run(data, false);
|
||||
}
|
||||
|
||||
Block Feistel::Decipher(const Block& data) {
|
||||
return Run(data, true);
|
||||
}
|
||||
|
||||
Block Feistel::Run(const Block& data, bool modeEncrypt) {
|
||||
if (!isInitialized) {
|
||||
throw std::runtime_error("Attempted to digest data on uninitialized GCipher!");
|
||||
}
|
||||
|
||||
const auto splitData = FeistelSplit(data);
|
||||
Halfblock l = splitData.first;
|
||||
Halfblock r = splitData.second;
|
||||
|
||||
Halfblock tmp;
|
||||
|
||||
for (std::size_t i = 0; i < N_ROUNDS; i++) {
|
||||
|
||||
// Encryption
|
||||
if (modeEncrypt) {
|
||||
const std::size_t keyIndex = i;
|
||||
|
||||
// Do a feistel round
|
||||
tmp = r;
|
||||
r = l ^ F(r, roundKeys[keyIndex]);
|
||||
l = tmp;
|
||||
|
||||
// Jumble it up a bit more
|
||||
l.ShiftRowsUpInplace();
|
||||
l.ShiftCellsRightInplace();
|
||||
l.ShiftBitsLeftInplace();
|
||||
l.ShiftColumnsLeftInplace();
|
||||
// Seal all these operations with a key
|
||||
l += ReductionFunction(roundKeys[keyIndex]);
|
||||
}
|
||||
|
||||
// Decryption
|
||||
else {
|
||||
// Decryption needs keys in reverse order
|
||||
const std::size_t keyIndex = N_ROUNDS - i - 1;
|
||||
|
||||
// Unjumble the jumble
|
||||
r -= ReductionFunction(roundKeys[keyIndex]);
|
||||
r.ShiftColumnsRightInplace();
|
||||
r.ShiftBitsRightInplace();
|
||||
r.ShiftCellsLeftInplace();
|
||||
r.ShiftRowsDownInplace();
|
||||
|
||||
// Do a feistel round
|
||||
tmp = r;
|
||||
r = l ^ F(r, roundKeys[keyIndex]);
|
||||
l = tmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Block has finished de*ciphering.
|
||||
// Let's generate a new set of round keys.
|
||||
GenerateRoundKeys(roundKeys.back());
|
||||
|
||||
return FeistelCombine(r, l);
|
||||
}
|
||||
|
||||
Halfblock Feistel::F(Halfblock m, const Key& key) {
|
||||
|
||||
// Made-up F function:
|
||||
// Expand to full bitwidth
|
||||
Block m_expanded = ExpansionFunction(m);
|
||||
|
||||
// Mix up the block a bit
|
||||
m_expanded.ShiftCellsRightInplace();
|
||||
m_expanded.ShiftRowsUpInplace();
|
||||
|
||||
// Matrix-mult with key (this is irreversible)
|
||||
m_expanded *= key;
|
||||
|
||||
// Now do a bitshift
|
||||
m_expanded.ShiftBitsLeftInplace();
|
||||
|
||||
// Apply the sbox
|
||||
SBox(m_expanded);
|
||||
|
||||
// Reduce back to a halfblock
|
||||
Halfblock hb = ReductionFunction(m_expanded);
|
||||
|
||||
// To jumble it up a last time,
|
||||
// matrix-multiply it with the input halfblock
|
||||
hb *= m;
|
||||
|
||||
return hb;
|
||||
}
|
||||
|
||||
std::pair<Halfblock, Halfblock> Feistel::FeistelSplit(const Block& block) {
|
||||
Halfblock l;
|
||||
Halfblock r;
|
||||
|
||||
memcpy(l.Data(), block.Data(), Halfblock::BLOCK_SIZE);
|
||||
memcpy(r.Data(), block.Data() + 8, Halfblock::BLOCK_SIZE);
|
||||
// +8, because 8 is HALF the number of elements in the array. We only want to copy HALF a full-sized block.
|
||||
|
||||
return std::make_pair(l, r);
|
||||
}
|
||||
|
||||
Block Feistel::FeistelCombine(const Halfblock& l, const Halfblock& r) {
|
||||
Block b;
|
||||
|
||||
memcpy(b.Data(), l.Data(), Halfblock::BLOCK_SIZE);
|
||||
memcpy(b.Data() + 8, r.Data(), Halfblock::BLOCK_SIZE);
|
||||
// +8, because 8 is HALF the number of elements in the array. We only want to copy HALF a full-sized block.
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
Block Feistel::ExpansionFunction(const Halfblock& hb) {
|
||||
Block b;
|
||||
|
||||
// Copy the bits over
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
b[i] = hb[i];
|
||||
}
|
||||
|
||||
// Multiply the block a few tims with a bitshifted version
|
||||
// This is irriversible, too
|
||||
for (std::size_t i = 0; i < 3; i++) {
|
||||
b *= b.ShiftBitsRight();
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
Halfblock Feistel::ReductionFunction(const Block& block) {
|
||||
|
||||
// Just apply a modulo operation, remapping a 32bit integer
|
||||
// onto 16bit space (default configuration).
|
||||
// Without saying, modulo is irreversible.
|
||||
Halfblock hb;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
hb[i] = block[i] % (1 << (Halfblock::CHUNK_SIZE_BITS - 1));
|
||||
}
|
||||
|
||||
return hb;
|
||||
}
|
||||
|
||||
void Feistel::SBox(Block& block) {
|
||||
|
||||
std::uint8_t* curByte = (std::uint8_t*)(void*)block.Data();
|
||||
|
||||
// Iterate over all bytes in the block
|
||||
for (std::size_t i = 0; i < Block::BLOCK_SIZE; i++) {
|
||||
curByte++;
|
||||
|
||||
// Subsitute byte
|
||||
*curByte = sboxLookup[*curByte];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
std::string Feistel::SBox(const std::string& in) {
|
||||
static std::unordered_map<std::string, std::string> subMap;
|
||||
static bool mapInitialized = false;
|
||||
if (!mapInitialized) {
|
||||
subMap["0000"] = "1100";
|
||||
subMap["0001"] = "1000";
|
||||
subMap["0010"] = "0001";
|
||||
subMap["0011"] = "0111";
|
||||
subMap["0100"] = "1011";
|
||||
subMap["0101"] = "0011";
|
||||
subMap["0110"] = "1101";
|
||||
subMap["0111"] = "1111";
|
||||
subMap["1000"] = "0000";
|
||||
subMap["1001"] = "1010";
|
||||
subMap["1010"] = "0100";
|
||||
subMap["1011"] = "1001";
|
||||
subMap["1100"] = "0010";
|
||||
subMap["1101"] = "1110";
|
||||
subMap["1110"] = "0101";
|
||||
subMap["1111"] = "0110";
|
||||
mapInitialized = true;
|
||||
}
|
||||
|
||||
return subMap[in];
|
||||
}
|
||||
*/
|
||||
|
||||
void Feistel::GenerateRoundKeys(const Key& seedKey) {
|
||||
// Clear initial key memory
|
||||
ZeroKeyMemory();
|
||||
roundKeys = Keyset();
|
||||
|
||||
// Derive all round keys with simple matrix operations
|
||||
roundKeys[0] = seedKey;
|
||||
|
||||
for (std::size_t i = 1; i < roundKeys.size(); i++) {
|
||||
// Initialize new round key with last round key
|
||||
const Key& lastKey = roundKeys[i - 1];
|
||||
roundKeys[i] = lastKey;
|
||||
|
||||
// Stir it good
|
||||
roundKeys[i].ShiftRowsUpInplace();
|
||||
|
||||
// Bitshift and matrix-mult 3 times
|
||||
// (each time jumbles it up pretty good)
|
||||
// This is irreversible
|
||||
roundKeys[i].ShiftBitsRightInplace();
|
||||
roundKeys[i] *= lastKey;
|
||||
roundKeys[i].ShiftBitsRightInplace();
|
||||
roundKeys[i] *= lastKey;
|
||||
roundKeys[i].ShiftBitsRightInplace();
|
||||
roundKeys[i] *= lastKey;
|
||||
|
||||
// Lastly, do apply some cell shifting, and other mutations
|
||||
roundKeys[i].ShiftCellsRightInplace();
|
||||
roundKeys[i] += lastKey;
|
||||
roundKeys[i].ShiftColumnsRightInplace();
|
||||
roundKeys[i] ^= lastKey;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Feistel::operator=(const Feistel& other) {
|
||||
roundKeys = other.roundKeys;
|
||||
isInitialized = other.isInitialized;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// These pragmas only work for MSVC and g++, as far as i know. Beware!!!
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
#pragma optimize("", off )
|
||||
#elif defined __GNUG__
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("O0")
|
||||
#endif
|
||||
void Feistel::ZeroKeyMemory() {
|
||||
for (Key& key : roundKeys) {
|
||||
key.Reset();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
#pragma optimize("", on )
|
||||
#elif defined __GNUG__
|
||||
#pragma GCC pop_options
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -1,91 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include "GCrypt/GCipher.h"
|
||||
#include "GCrypt/Util.h"
|
||||
#include "GCrypt/InitializationVector.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
GCipher::GCipher() {
|
||||
}
|
||||
|
||||
GCipher::GCipher(const Key& key, const DIRECTION direction) :
|
||||
direction { direction },
|
||||
lastBlock(InitializationVector(key)), // Initialize our lastBlock with some deterministic initial value, based on the key
|
||||
feistel(key)
|
||||
{
|
||||
isInitialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
void GCipher::Initialize(const Key& key, const DIRECTION direction) {
|
||||
feistel = Feistel(key);
|
||||
lastBlock = InitializationVector(key);
|
||||
this->direction = direction;
|
||||
isInitialized = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Block GCipher::Digest(const Block& input) {
|
||||
|
||||
if (!isInitialized) {
|
||||
throw std::runtime_error("Attempted to digest data on uninitialized GCipher!");
|
||||
}
|
||||
|
||||
switch (direction) {
|
||||
case DIRECTION::ENCIPHER: {
|
||||
// Rename our input to cleartext
|
||||
const Block& cleartext = input;
|
||||
|
||||
// First, xor our cleartext with the last block, and then encipher it
|
||||
Block ciphertext = feistel.Encipher(cleartext ^ lastBlock);
|
||||
|
||||
// Now set our lastBlock to the ciphertext of this block
|
||||
lastBlock = ciphertext;
|
||||
|
||||
// Now return the ciphertext
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
case DIRECTION::DECIPHER: {
|
||||
// Rename our input into ciphertext
|
||||
const Block& ciphertext = input;
|
||||
|
||||
// First, decipher our ciphertext, and then xor it with our last block
|
||||
Block cleartext = feistel.Decipher(ciphertext) ^ lastBlock;
|
||||
|
||||
// Now set our lastBLock to the ciphertext of this block
|
||||
lastBlock = ciphertext;
|
||||
|
||||
// Now return the cleartext
|
||||
return cleartext;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unreachable branch reached.");
|
||||
}
|
||||
|
||||
void GCipher::SetKey(const Key& key) {
|
||||
|
||||
if (!isInitialized) {
|
||||
throw std::runtime_error("Attempted to set key on uninitialized GCipher!");
|
||||
}
|
||||
|
||||
feistel.SetKey(key);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void GCipher::operator=(const GCipher& other) {
|
||||
direction = other.direction;
|
||||
feistel = other.feistel;
|
||||
lastBlock = other.lastBlock;
|
||||
isInitialized = other.isInitialized;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,97 +0,0 @@
|
||||
#include "GCrypt/GHash.h"
|
||||
#include "GCrypt/Util.h"
|
||||
#include "GCrypt/InitializationVector.h"
|
||||
#include <vector>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
GHash::GHash() {
|
||||
// Initialize our cipher with a static, but randomly distributed key.
|
||||
Block ivSeed;
|
||||
ivSeed.FromByteString("3J7IipfQTDJbO8jtasz9PgWui6faPaEMOuVuAqyhB1S2CRcLw5caawewgDUEG1WN");
|
||||
block = InitializationVector(ivSeed);
|
||||
|
||||
Key key;
|
||||
key.FromByteString("nsoCZfvdqpRkeVTt9wzvPR3TT26peOW9E2kTHh3pdPCq2M7BpskvUljJHSrobUTI");
|
||||
|
||||
cipher = GCipher(
|
||||
// The key really does not matter, as it gets changed
|
||||
// each time before digesting anything.
|
||||
key,
|
||||
GCipher::DIRECTION::ENCIPHER
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void GHash::Digest(const Block& data) {
|
||||
// Set the cipher key to the current data to be hashed
|
||||
cipher.SetKey(data);
|
||||
|
||||
// Encipher the current block, and matrix-mult it with the current hashsum
|
||||
block ^= cipher.Digest(data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const Block& GHash::GetHashsum() const {
|
||||
return block;
|
||||
}
|
||||
|
||||
Block GHash::CalculateHashsum(const std::vector<Block>& data, std::size_t n_bytes) {
|
||||
|
||||
// If we have no supplied n_bytes, let's just assume sizeof(data).
|
||||
if (n_bytes == std::string::npos) {
|
||||
n_bytes = data.size() * Block::BLOCK_SIZE;
|
||||
}
|
||||
|
||||
// Create hasher instance
|
||||
GHash hasher;
|
||||
|
||||
// Digest all blocks
|
||||
for (const Block& block : data) {
|
||||
hasher.Digest(block);
|
||||
}
|
||||
|
||||
// Add an additional block, containing the length of the input
|
||||
|
||||
// Here it is actually good to use a binary string ("10011"),
|
||||
// because std::size_t is not fixed to 32-bits. It may aswell
|
||||
// be 64 bits, depending on the platform.
|
||||
// Then it would be BAD to just cram it into a 32-bit uint32.
|
||||
// This way, in case of 64-bits, it would just occupy 2 uint32's.
|
||||
|
||||
// Also, this operation gets done ONCE per n blocks. This won't
|
||||
// hurt performance.
|
||||
|
||||
// I know that we are first converting n_bytes to str(n_bytes),
|
||||
// and then converting this to a binstring, making it unnecessarily large,
|
||||
// but who cares. It has a whole 512 bit block to itself.
|
||||
// The max size (2^64) would occupy 155 bits at max. (log10(2^64)*8 = 155)
|
||||
|
||||
std::stringstream ss;
|
||||
ss << n_bytes;
|
||||
Block lengthBlock;
|
||||
lengthBlock.FromTextString(ss.str());
|
||||
|
||||
// Digest the length block
|
||||
hasher.Digest(lengthBlock);
|
||||
|
||||
// Return the total hashsum
|
||||
return hasher.GetHashsum();
|
||||
}
|
||||
|
||||
Block GHash::HashString(const std::string& str) {
|
||||
const std::vector<Block> blocks = StringToBitblocks(str);
|
||||
const std::size_t n_bytes = str.length();
|
||||
|
||||
return CalculateHashsum(blocks, n_bytes);
|
||||
}
|
||||
|
||||
void GHash::operator=(const GHash& other) {
|
||||
cipher = other.cipher;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1,116 +0,0 @@
|
||||
#include "GCrypt/GPrng.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
GPrng::GPrng(const Block& seed) {
|
||||
this->seed = seed;
|
||||
hasher.Digest(seed);
|
||||
}
|
||||
|
||||
GPrng::GPrng() {
|
||||
}
|
||||
|
||||
void GPrng::Seed(const Block& seed) {
|
||||
hasher = GHash();
|
||||
this->seed = seed;
|
||||
hasher.Digest(seed);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool GPrng::GetBit() {
|
||||
// If we have no more bits to go, create new ones
|
||||
if (nextBit >= Block::BLOCK_SIZE_BITS) {
|
||||
AdvanceBlock();
|
||||
}
|
||||
|
||||
// Return the next bit.
|
||||
return hasher.GetHashsum().GetBit(nextBit++);
|
||||
}
|
||||
|
||||
void GPrng::AdvanceBlock() {
|
||||
// To prevent an attacker from being able
|
||||
// to predict block n, by knowing block n-1, and block n-2,
|
||||
// we will advance the hash function by block n-1 XOR seed.
|
||||
// This way it is impossible for an attacker to know the
|
||||
// state of the hash function, unless the seed is known.
|
||||
|
||||
// Advance the block (Add the current hashsum XOR seed to the hasher)
|
||||
hasher.Digest(Block(hasher.GetHashsum() ^ seed));
|
||||
|
||||
// Reset the pointer
|
||||
nextBit = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Block GPrng::GetBlock() {
|
||||
// Tactic on efficiently generating a new block:
|
||||
// 1) Fetch complete current hashsum (it might have been partially given out already)
|
||||
// 2) Bitshift it, and matrix-mult it with the seed (that is irreversible)
|
||||
// That should be a one-way function, and create a new unique block.
|
||||
|
||||
// Performance improvement over the previous method:
|
||||
// (generating 100.000 blocks):
|
||||
// 12 seconds -> 0.12 seconds
|
||||
|
||||
// Fetch our current block
|
||||
Block hashsum = hasher.GetHashsum();
|
||||
|
||||
// Derive/'hash' it to hashsum'
|
||||
hashsum *= seed;
|
||||
hashsum.ShiftBitsLeftInplace();
|
||||
hashsum *= seed;
|
||||
|
||||
// Advance the block, so that the following block will be a new block
|
||||
AdvanceBlock();
|
||||
|
||||
// Return our hashsum
|
||||
return hashsum;
|
||||
}
|
||||
|
||||
std::uint32_t GPrng::operator()() {
|
||||
// Tactic:
|
||||
// A block intrinsically consists of 16 32-bit uints.
|
||||
// We'll just skip all the bits until the next whole integer,
|
||||
// fetch this complete int, and then advance our pointer
|
||||
// by 32 bits.
|
||||
|
||||
// Performance improvement over the previous method:
|
||||
// (generating 1.000.000 integers):
|
||||
// 5.26 seconds -> 3.75 seconds
|
||||
|
||||
|
||||
// Advance our pointer to the next whole uint32
|
||||
|
||||
// Do we even have >= 32 bits left in our block?
|
||||
if (nextBit > Block::BLOCK_SIZE_BITS - Block::CHUNK_SIZE_BITS) {
|
||||
// No: Create a new block
|
||||
AdvanceBlock();
|
||||
}
|
||||
|
||||
// We don't have to do this, if our pointer is already at
|
||||
// the beginning of a whole uint32
|
||||
if (nextBit % Block::CHUNK_SIZE_BITS != 0) {
|
||||
nextBit = ((nextBit / Block::CHUNK_SIZE_BITS) + 1) * Block::CHUNK_SIZE_BITS;
|
||||
}
|
||||
|
||||
// Fetch our integer from the block
|
||||
const std::uint32_t randint =
|
||||
hasher.GetHashsum().Get(nextBit / Block::CHUNK_SIZE_BITS);
|
||||
|
||||
// Advance our pointer
|
||||
nextBit += Block::CHUNK_SIZE_BITS;
|
||||
|
||||
// New state of the pointer:
|
||||
// It ow may be more now than the size of a block, but that
|
||||
// gets checked at the begin of a function.
|
||||
// Not at the end, like here.
|
||||
|
||||
// Return our integer
|
||||
return randint;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,158 +0,0 @@
|
||||
#include "GCrypt/GWrapper.h"
|
||||
#include "GCrypt/GCipher.h"
|
||||
#include "GCrypt/Util.h"
|
||||
#include <vector>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
std::string GWrapper::EncryptString(
|
||||
const std::string& cleartext,
|
||||
const Key& key)
|
||||
{
|
||||
// Recode the ascii-string to bits
|
||||
const std::vector<Block> cleartext_blocks = StringToBitblocks(cleartext);
|
||||
|
||||
// Create cipher instance
|
||||
GCipher cipher(key, GCipher::DIRECTION::ENCIPHER);
|
||||
|
||||
// Encrypt all blocks
|
||||
std::vector<Block> ciphertext_blocks;
|
||||
|
||||
for (const Block& clearBlock : cleartext_blocks) {
|
||||
ciphertext_blocks.emplace_back(cipher.Digest(clearBlock));
|
||||
}
|
||||
|
||||
// Recode the ciphertext blocks to a hex-string
|
||||
std::stringstream ss;
|
||||
for (const Block& block : ciphertext_blocks) {
|
||||
ss << block.ToHexString();
|
||||
}
|
||||
|
||||
// Return it
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string GWrapper::DecryptString(
|
||||
const std::string& ciphertext,
|
||||
const Key& key)
|
||||
{
|
||||
// Make sure our ciphertext is a multiple of block size
|
||||
if (ciphertext.length() % Block::BLOCK_SIZE*2 != 0) { // Two chars per byte
|
||||
throw std::runtime_error("Leonetienne::GCrypt::GWrapper::DecryptString() received ciphertext of length not a multiple of block size.");
|
||||
}
|
||||
|
||||
// Recode the hex-string to blocks
|
||||
std::vector<Block> ciphertext_blocks;
|
||||
ciphertext_blocks.reserve(ciphertext.length() / (Block::BLOCK_SIZE*2));
|
||||
for (std::size_t i = 0; i < ciphertext.length(); i += Block::BLOCK_SIZE*2) {
|
||||
Block block;
|
||||
block.FromHexString(ciphertext.substr(i, Block::BLOCK_SIZE*2));
|
||||
|
||||
ciphertext_blocks.emplace_back(block);
|
||||
}
|
||||
|
||||
// Create cipher instance
|
||||
GCipher cipher(key, GCipher::DIRECTION::DECIPHER);
|
||||
|
||||
// Decrypt all blocks
|
||||
std::vector<Block> cleartext_blocks;
|
||||
for (const Block& cipherBlock : ciphertext_blocks) {
|
||||
cleartext_blocks.emplace_back(cipher.Digest(cipherBlock));
|
||||
}
|
||||
|
||||
// Recode the cleartext blocks to bytes
|
||||
std::stringstream ss;
|
||||
for (const Block& block : cleartext_blocks) {
|
||||
ss << block.ToTextString();
|
||||
}
|
||||
|
||||
// Return it
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool GWrapper::EncryptFile(
|
||||
const std::string& filename_in,
|
||||
const std::string& filename_out,
|
||||
const Key& key,
|
||||
bool printProgressReport)
|
||||
{
|
||||
try {
|
||||
// Read the file to blocks
|
||||
const std::vector<Block> cleartext_blocks = ReadFileToBlocks(filename_in);
|
||||
|
||||
// Encrypt our cleartext blocks
|
||||
std::vector<Block> ciphertext_blocks;
|
||||
ciphertext_blocks.reserve(cleartext_blocks.size());
|
||||
|
||||
// Create cipher instance
|
||||
GCipher cipher(key, GCipher::DIRECTION::ENCIPHER);
|
||||
|
||||
// Encrypt all blocks
|
||||
for (const Block& clearBlock : cleartext_blocks) {
|
||||
ciphertext_blocks.emplace_back(cipher.Digest(clearBlock));
|
||||
}
|
||||
|
||||
// Write our ciphertext blocks to file
|
||||
WriteBlocksToFile(filename_out, ciphertext_blocks);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (std::runtime_error&) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool GWrapper::DecryptFile(
|
||||
const std::string& filename_in,
|
||||
const std::string& filename_out,
|
||||
const Key& key,
|
||||
bool printProgressReport)
|
||||
{
|
||||
try {
|
||||
// Read the file to blocks
|
||||
const std::vector<Block> ciphertext_blocks = ReadFileToBlocks(filename_in);
|
||||
|
||||
// Decrypt our cleartext blocks
|
||||
std::vector<Block> cleartext_blocks;
|
||||
cleartext_blocks.reserve(ciphertext_blocks.size());
|
||||
|
||||
// Create cipher instance
|
||||
GCipher cipher(key, GCipher::DIRECTION::DECIPHER);
|
||||
|
||||
// Decrypt all blocks
|
||||
for (const Block& cipherBlock : ciphertext_blocks) {
|
||||
cleartext_blocks.emplace_back(cipher.Digest(cipherBlock));
|
||||
}
|
||||
|
||||
// Write our cleartext blocks to file
|
||||
WriteBlocksToFile(filename_out, cleartext_blocks);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (std::runtime_error&) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Block> GWrapper::CipherBlocks(
|
||||
const std::vector<Block>& data,
|
||||
const Key& key,
|
||||
const GCipher::DIRECTION direction)
|
||||
{
|
||||
// Create cipher instance
|
||||
GCipher cipher(key, direction);
|
||||
|
||||
std::vector<Block> digested;
|
||||
digested.reserve(data.size());
|
||||
|
||||
// Digest all our blocks
|
||||
for (const Block& block : data) {
|
||||
Block digestedBlock = cipher.Digest(block);
|
||||
digested.emplace_back(digestedBlock);
|
||||
}
|
||||
|
||||
// Return it
|
||||
return digested;
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
#include "GCrypt/InitializationVector.h"
|
||||
#include "GCrypt/Feistel.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
InitializationVector::InitializationVector(const Block& seed) {
|
||||
// We'll generate our initialization vector by encrypting our seed with itself as a key
|
||||
// iv = E(M=seed, K=seed)
|
||||
iv = Feistel(seed).Encipher(seed);
|
||||
}
|
||||
|
||||
InitializationVector::operator Block() const {
|
||||
return iv;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,75 +0,0 @@
|
||||
#include "GCrypt/Key.h"
|
||||
#include "GCrypt/GHash.h"
|
||||
#include "GCrypt/Util.h"
|
||||
#include <random>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
Key Key::FromPassword(const std::string& password) {
|
||||
return GHash::HashString(password);
|
||||
}
|
||||
|
||||
Key Key::Random() {
|
||||
// Create our truly-random rng
|
||||
std::random_device rng;
|
||||
constexpr std::size_t bitsPerCall = sizeof(std::random_device::result_type) * 8;
|
||||
|
||||
// Create a new key, and assign 16 random values
|
||||
Key key;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
key[i] = rng();
|
||||
}
|
||||
|
||||
// Return it
|
||||
return key;
|
||||
}
|
||||
|
||||
Key Key::LoadFromFile(const std::string& path) {
|
||||
// Read this many chars
|
||||
const std::size_t maxChars = Key::BLOCK_SIZE;
|
||||
|
||||
// Open ifilestream for keyfile
|
||||
std::ifstream ifs(path, std::ios::in | std::ios::binary);
|
||||
|
||||
// Is the file open now? Or were there any issues...
|
||||
if (!ifs.good()) {
|
||||
throw std::runtime_error(std::string("Unable to open ifilestream for keyfile \"") + path + "\"! Aborting...");
|
||||
}
|
||||
|
||||
// Create a new key, and zero it
|
||||
Key key;
|
||||
key.Reset();
|
||||
|
||||
// Read into it
|
||||
ifs.read((char*)(void*)key.Data(), Key::BLOCK_SIZE);
|
||||
|
||||
// Return it
|
||||
return key;
|
||||
}
|
||||
|
||||
void Key::WriteToFile(const std::string& path) const {
|
||||
// Create an ofilestream
|
||||
std::ofstream ofs(path, std::ios::out | std::ios::binary);
|
||||
|
||||
// Write the key
|
||||
ofs.write((char*)(void*)Data(), Key::BLOCK_SIZE);
|
||||
|
||||
// Close the file handle
|
||||
ofs.close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Key::Key() : Block() {
|
||||
}
|
||||
|
||||
Key::Key(const Block& b) : Block(b) {
|
||||
}
|
||||
|
||||
Key::Key(const Key& k) : Block(k) {
|
||||
}
|
||||
}
|
||||
|
@ -1,142 +0,0 @@
|
||||
#include "GCrypt/Util.h"
|
||||
#include "GCrypt/GHash.h"
|
||||
#include <vector>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
std::string PadStringToLength(const std::string& str, const std::size_t len, const char pad, const bool padLeft) {
|
||||
// Fast-reject: Already above padded length
|
||||
if (str.length() >= len) {
|
||||
return str;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
// Pad left:
|
||||
if (padLeft) {
|
||||
for (std::size_t i = 0; i < len - str.size(); i++) {
|
||||
ss << pad;
|
||||
}
|
||||
ss << str;
|
||||
}
|
||||
// Pad right:
|
||||
else {
|
||||
ss << str;
|
||||
for (std::size_t i = 0; i < len - str.size(); i++) {
|
||||
ss << pad;
|
||||
}
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string BitblocksToBytes(const std::vector<Block>& blocks) {
|
||||
std::stringstream ss;
|
||||
|
||||
for (const Block& block : blocks) {
|
||||
ss << block.ToByteString();
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string BitblocksToString(const std::vector<Block>& blocks) {
|
||||
// Decode to bytes
|
||||
std::string text = BitblocksToBytes(blocks);
|
||||
|
||||
// Dümp excess nullbytes
|
||||
text.resize(strlen(text.data()));
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
std::vector<Block> ReadFileToBlocks(const std::string& filepath, std::size_t& bytes_read) {
|
||||
// Read file
|
||||
bytes_read = 0;
|
||||
|
||||
// "ate" specifies that the read-pointer is already at the end of the file
|
||||
// this allows to estimate the file size
|
||||
std::ifstream ifs(filepath, std::ios::binary | std::ios::ate);
|
||||
|
||||
if (!ifs.good()) {
|
||||
throw std::runtime_error("Unable to open ifilestream!");
|
||||
}
|
||||
|
||||
// Create our vector of blocks, and resorve a good guess
|
||||
// of memory
|
||||
std::vector<Block> blocks;
|
||||
blocks.reserve((ifs.tellg() / Block::BLOCK_SIZE) + 1);
|
||||
|
||||
// Move read head to the file beginning
|
||||
ifs.seekg(std::ios_base::beg);
|
||||
|
||||
// Whilst not reached eof, read into blocks
|
||||
while (!ifs.eof()) {
|
||||
// Create a new block, and zero it
|
||||
Block block;
|
||||
block.Reset();
|
||||
|
||||
// Read data into the block
|
||||
ifs.read((char*)(void*)block.Data(), Block::BLOCK_SIZE);
|
||||
const std::size_t n_bytes_read_block = ifs.gcount();
|
||||
bytes_read += n_bytes_read_block;
|
||||
|
||||
if (n_bytes_read_block > 0) {
|
||||
// Append the block to our vector
|
||||
blocks.emplace_back(block);
|
||||
}
|
||||
}
|
||||
|
||||
// Close the filehandle
|
||||
ifs.close();
|
||||
|
||||
return blocks;
|
||||
}
|
||||
|
||||
std::vector<Block> ReadFileToBlocks(const std::string& filepath) {
|
||||
std::size_t bytes_read_dummy; // Create a dumme for the parameter
|
||||
return ReadFileToBlocks(filepath, bytes_read_dummy);
|
||||
}
|
||||
|
||||
void WriteBlocksToFile(
|
||||
const std::string& filepath,
|
||||
const std::vector<Block>& blocks
|
||||
){
|
||||
|
||||
// Create outfile file handle
|
||||
std::ofstream ofs(filepath, std::ios::binary);
|
||||
|
||||
if (!ofs.good()) {
|
||||
throw std::runtime_error("Unable to open ofilestream!");
|
||||
}
|
||||
|
||||
// Write all the blocks
|
||||
for (const Block& block : blocks) {
|
||||
ofs.write((char*)(void*)block.Data(), Block::BLOCK_SIZE);
|
||||
}
|
||||
|
||||
// Close the filehandle
|
||||
ofs.close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<Block> StringToBitblocks(const std::string& str) {
|
||||
|
||||
// Create our block vector, and reserve exactly
|
||||
// how many blocks are required to store this string
|
||||
const std::size_t num_blocks = (str.length() / Block::BLOCK_SIZE) + 1;
|
||||
std::vector<Block> blocks;
|
||||
blocks.reserve(num_blocks);
|
||||
|
||||
for (std::size_t i = 0; i < str.length(); i += Block::BLOCK_SIZE) {
|
||||
Block block;
|
||||
block.FromTextString(str.substr(i, Block::BLOCK_SIZE));
|
||||
|
||||
blocks.emplace_back(block);
|
||||
}
|
||||
|
||||
return blocks;
|
||||
}
|
||||
}
|
||||
|
@ -1,902 +0,0 @@
|
||||
#include <GCrypt/Block.h>
|
||||
#include <GCrypt/Key.h>
|
||||
#include "Catch2.h"
|
||||
#include <cstdlib>
|
||||
#include <time.h>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
// Tests that writing and retrieving data from a block works
|
||||
TEST_CASE(__FILE__"/Write-read", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block;
|
||||
|
||||
// Exercise
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
// Verify
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
REQUIRE(block.Get(i) == i * 1024);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that the copy constructor works
|
||||
TEST_CASE(__FILE__"/CCtor", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
// Exercise
|
||||
Block block2(block);
|
||||
|
||||
// Verify
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
REQUIRE(block2.Get(i) == i * 1024);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that operator= works
|
||||
TEST_CASE(__FILE__"/operator=", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
// Exercise
|
||||
Block block2;
|
||||
block2 = block;
|
||||
|
||||
// Verify
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
REQUIRE(block2.Get(i) == i * 1024);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that converting to, and from, binary strings works
|
||||
TEST_CASE(__FILE__"/BinaryStringConversion", "[Block]") {
|
||||
|
||||
// Setup
|
||||
srand(time(0));
|
||||
std::stringstream ss;
|
||||
|
||||
for (std::size_t i = 0; i < 512; i++) {
|
||||
ss << (rand()%2 == 0 ? '1' : '0');
|
||||
}
|
||||
|
||||
// Exercise
|
||||
Block block(ss.str());
|
||||
|
||||
// Verify
|
||||
REQUIRE(block.ToBinaryString() == ss.str());
|
||||
}
|
||||
|
||||
// Tests that converting to, and from, hexstrings works
|
||||
TEST_CASE(__FILE__"/HexStringConversion", "[Block]") {
|
||||
|
||||
// Setup
|
||||
srand(time(0));
|
||||
std::stringstream ss;
|
||||
|
||||
const std::string charset = "0123456789abcdef";
|
||||
for (std::size_t i = 0; i < 128; i++) {
|
||||
ss << charset[rand() % charset.length()];
|
||||
}
|
||||
|
||||
// Exercise
|
||||
Block block;
|
||||
block.FromHexString(ss.str());
|
||||
|
||||
// Verify
|
||||
REQUIRE(block.ToHexString() == ss.str());
|
||||
}
|
||||
|
||||
// Tests that converting to, and from, bytestrings works
|
||||
TEST_CASE(__FILE__"/ByteStringConversion", "[Block]") {
|
||||
|
||||
// Setup
|
||||
srand(time(0));
|
||||
std::stringstream ss;
|
||||
|
||||
for (std::size_t i = 0; i < 64; i++) {
|
||||
ss << (char)(rand() % 256);
|
||||
}
|
||||
|
||||
// Exercise
|
||||
Block block;
|
||||
block.FromByteString(ss.str());
|
||||
|
||||
// Verify
|
||||
REQUIRE(block.ToByteString() == ss.str());
|
||||
}
|
||||
|
||||
// Tests that converting to, and from, textstrings works
|
||||
TEST_CASE(__FILE__"/TextStringConversion", "[Block]") {
|
||||
|
||||
// Setup
|
||||
const std::string textstr = "Hello, World :3";
|
||||
|
||||
// Exercise
|
||||
Block block;
|
||||
block.FromTextString(textstr);
|
||||
|
||||
// Verify
|
||||
REQUIRE(block.ToTextString() == textstr);
|
||||
}
|
||||
|
||||
// Tests that operator* is the same as *=
|
||||
TEST_CASE(__FILE__"/operator*&=", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block1;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block1.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
Block block2;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block2.Get(i) = i * 1024 * 2;
|
||||
}
|
||||
|
||||
// Exercise
|
||||
Block block3 = block1 * block2;
|
||||
block1 *= block2;
|
||||
|
||||
// Verify
|
||||
REQUIRE(block1 == block3);
|
||||
}
|
||||
|
||||
// Tests that operator^ (xor) works
|
||||
TEST_CASE(__FILE__"/xor", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
Block xorRH;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
xorRH.Get(i) = i * 5099;
|
||||
}
|
||||
|
||||
// Exercise
|
||||
Block result = block ^ xorRH;
|
||||
|
||||
Block manualResult;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
manualResult.Get(i) = (i * 1024) ^ (i * 5099);
|
||||
}
|
||||
|
||||
// Verify
|
||||
REQUIRE(result == manualResult);
|
||||
}
|
||||
|
||||
// Tests that operator^ is the same as ^=
|
||||
TEST_CASE(__FILE__"/operator^&=", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block1;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block1.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
Block block2;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block2.Get(i) = i * 5099 * 2;
|
||||
}
|
||||
|
||||
// Exercise
|
||||
Block block3 = block1 ^ block2;
|
||||
block1 ^= block2;
|
||||
|
||||
// Verify
|
||||
REQUIRE(block1 == block3);
|
||||
}
|
||||
|
||||
// Tests that operator+ (add) works
|
||||
TEST_CASE(__FILE__"/add", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
Block addRH;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
addRH.Get(i) = i * 5099;
|
||||
}
|
||||
|
||||
// Exercise
|
||||
Block result = block + addRH;
|
||||
|
||||
Block manualResult;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
manualResult.Get(i) = (i * 1024) + (i * 5099);
|
||||
}
|
||||
|
||||
// Verify
|
||||
REQUIRE(result == manualResult);
|
||||
}
|
||||
|
||||
// Tests that operator+ is the same as +=
|
||||
TEST_CASE(__FILE__"/operator+&=", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block1;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block1.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
Block block2;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block2.Get(i) = i * 5099 * 2;
|
||||
}
|
||||
|
||||
// Exercise
|
||||
Block block3 = block1 + block2;
|
||||
block1 += block2;
|
||||
|
||||
// Verify
|
||||
REQUIRE(block1 == block3);
|
||||
}
|
||||
|
||||
// Tests that operator- (subtract) works
|
||||
TEST_CASE(__FILE__"/subtract", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
Block subRH;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
subRH.Get(i) = i * 5099;
|
||||
}
|
||||
|
||||
// Exercise
|
||||
Block result = block - subRH;
|
||||
|
||||
Block manualResult;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
manualResult.Get(i) = (i * 1024) - (i * 5099);
|
||||
}
|
||||
|
||||
// Verify
|
||||
REQUIRE(result == manualResult);
|
||||
}
|
||||
|
||||
// Tests that operator- is the same as -=
|
||||
TEST_CASE(__FILE__"/operator-&=", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block1;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block1.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
Block block2;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block2.Get(i) = i * 5099 * 2;
|
||||
}
|
||||
|
||||
// Exercise
|
||||
Block block3 = block1 - block2;
|
||||
block1 -= block2;
|
||||
|
||||
// Verify
|
||||
REQUIRE(block1 == block3);
|
||||
}
|
||||
|
||||
// Tests that subtraction undoes addition, and vica versa
|
||||
TEST_CASE(__FILE__"/subtraction-undoes-addition", "[Block]") {
|
||||
// Setup
|
||||
const Block a = Key::Random();
|
||||
const Block b = Key::Random();
|
||||
|
||||
// Exercise
|
||||
const Block a_plus_b = a + b;
|
||||
const Block a_plus_b_minus_b = a_plus_b - b;
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == a_plus_b_minus_b);
|
||||
}
|
||||
|
||||
// Tests that operator== works correctly
|
||||
TEST_CASE(__FILE__"/operator==", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
SECTION("Expected true") {
|
||||
Block sameBlock;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
sameBlock.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
REQUIRE(block == sameBlock);
|
||||
}
|
||||
|
||||
SECTION("Expected false") {
|
||||
Block otherBlock;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
otherBlock.Get(i) = i * 1024 + 1;
|
||||
}
|
||||
|
||||
REQUIRE_FALSE(block == otherBlock);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that operator!= works correctly
|
||||
TEST_CASE(__FILE__"/operator!=", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
SECTION("Expected false") {
|
||||
Block sameBlock;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
sameBlock.Get(i) = i * 1024;
|
||||
}
|
||||
|
||||
REQUIRE_FALSE(block != sameBlock);
|
||||
}
|
||||
|
||||
SECTION("Expected true") {
|
||||
Block otherBlock;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
otherBlock.Get(i) = i * 1024 + 1;
|
||||
}
|
||||
|
||||
REQUIRE(block != otherBlock);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that getting the data via the matrix accessor works
|
||||
TEST_CASE(__FILE__"/matrix-accessor", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block.Get(i) = i;
|
||||
}
|
||||
|
||||
// Exercise
|
||||
REQUIRE(block.Get(0,0) == 0);
|
||||
REQUIRE(block.Get(1,0) == 1);
|
||||
REQUIRE(block.Get(2,0) == 2);
|
||||
REQUIRE(block.Get(3,0) == 3);
|
||||
REQUIRE(block.Get(0,1) == 4);
|
||||
REQUIRE(block.Get(1,1) == 5);
|
||||
REQUIRE(block.Get(2,1) == 6);
|
||||
REQUIRE(block.Get(3,1) == 7);
|
||||
REQUIRE(block.Get(0,2) == 8);
|
||||
REQUIRE(block.Get(1,2) == 9);
|
||||
REQUIRE(block.Get(2,2) == 10);
|
||||
REQUIRE(block.Get(3,2) == 11);
|
||||
REQUIRE(block.Get(0,3) == 12);
|
||||
REQUIRE(block.Get(1,3) == 13);
|
||||
REQUIRE(block.Get(2,3) == 14);
|
||||
REQUIRE(block.Get(3,3) == 15);
|
||||
}
|
||||
|
||||
// Tests that the reset method works
|
||||
TEST_CASE(__FILE__"/reset", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block block;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
block.Get(i) = i + 33;
|
||||
}
|
||||
|
||||
// Exercise
|
||||
block.Reset();
|
||||
|
||||
// Verify
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
REQUIRE(block[i] == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that shift rows up works
|
||||
TEST_CASE(__FILE__"/shift-rows-up", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block a;
|
||||
a.Get(0,0) = 10; a.Get(0,1) = 11; a.Get(0,2) = 12; a.Get(0,3) = 13;
|
||||
a.Get(1,0) = 20; a.Get(1,1) = 21; a.Get(1,2) = 22; a.Get(1,3) = 23;
|
||||
a.Get(2,0) = 30; a.Get(2,1) = 31; a.Get(2,2) = 32; a.Get(2,3) = 33;
|
||||
a.Get(3,0) = 40; a.Get(3,1) = 41; a.Get(3,2) = 42; a.Get(3,3) = 43;
|
||||
|
||||
Block e; /* expected */
|
||||
e.Get(0,0) = 20; e.Get(0,1) = 21; e.Get(0,2) = 22; e.Get(0,3) = 23;
|
||||
e.Get(1,0) = 30; e.Get(1,1) = 31; e.Get(1,2) = 32; e.Get(1,3) = 33;
|
||||
e.Get(2,0) = 40; e.Get(2,1) = 41; e.Get(2,2) = 42; e.Get(2,3) = 43;
|
||||
e.Get(3,0) = 10; e.Get(3,1) = 11; e.Get(3,2) = 12; e.Get(3,3) = 13;
|
||||
|
||||
// Exercise
|
||||
a.ShiftRowsUpInplace();
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == e);
|
||||
}
|
||||
|
||||
// Tests that ShiftRowsUpInplace() does the exact same thing as ShiftRowsUp()
|
||||
TEST_CASE(__FILE__"/shift-rows-up-same-as-inplace", "[Block]") {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
const Block initial_a = a;
|
||||
|
||||
// Exercise and verify
|
||||
a.ShiftRowsUpInplace();
|
||||
REQUIRE(a == initial_a.ShiftRowsUp());
|
||||
}
|
||||
|
||||
// Tests that shift rows down works
|
||||
TEST_CASE(__FILE__"/shift-rows-down", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block a;
|
||||
a.Get(0,0) = 10; a.Get(0,1) = 11; a.Get(0,2) = 12; a.Get(0,3) = 13;
|
||||
a.Get(1,0) = 20; a.Get(1,1) = 21; a.Get(1,2) = 22; a.Get(1,3) = 23;
|
||||
a.Get(2,0) = 30; a.Get(2,1) = 31; a.Get(2,2) = 32; a.Get(2,3) = 33;
|
||||
a.Get(3,0) = 40; a.Get(3,1) = 41; a.Get(3,2) = 42; a.Get(3,3) = 43;
|
||||
|
||||
Block e; /* expected */
|
||||
e.Get(0,0) = 40; e.Get(0,1) = 41; e.Get(0,2) = 42; e.Get(0,3) = 43;
|
||||
e.Get(1,0) = 10; e.Get(1,1) = 11; e.Get(1,2) = 12; e.Get(1,3) = 13;
|
||||
e.Get(2,0) = 20; e.Get(2,1) = 21; e.Get(2,2) = 22; e.Get(2,3) = 23;
|
||||
e.Get(3,0) = 30; e.Get(3,1) = 31; e.Get(3,2) = 32; e.Get(3,3) = 33;
|
||||
|
||||
// Exercise
|
||||
a.ShiftRowsDownInplace();
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == e);
|
||||
}
|
||||
|
||||
// Tests that ShiftRowsDownInplace() does the exact same thing as ShiftRowsDown()
|
||||
TEST_CASE(__FILE__"/shift-rows-down-same-as-inplace", "[Block]") {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
const Block initial_a = a;
|
||||
|
||||
// Exercise and verify
|
||||
a.ShiftRowsDownInplace();
|
||||
REQUIRE(a == initial_a.ShiftRowsDown());
|
||||
}
|
||||
|
||||
// Tests that shift columns left works
|
||||
TEST_CASE(__FILE__"/shift-columns-left", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block a;
|
||||
a.Get(0,0) = 10; a.Get(0,1) = 11; a.Get(0,2) = 12; a.Get(0,3) = 13;
|
||||
a.Get(1,0) = 20; a.Get(1,1) = 21; a.Get(1,2) = 22; a.Get(1,3) = 23;
|
||||
a.Get(2,0) = 30; a.Get(2,1) = 31; a.Get(2,2) = 32; a.Get(2,3) = 33;
|
||||
a.Get(3,0) = 40; a.Get(3,1) = 41; a.Get(3,2) = 42; a.Get(3,3) = 43;
|
||||
|
||||
Block e; /* expected */
|
||||
e.Get(0,0) = 11; e.Get(0,1) = 12; e.Get(0,2) = 13; e.Get(0,3) = 10;
|
||||
e.Get(1,0) = 21; e.Get(1,1) = 22; e.Get(1,2) = 23; e.Get(1,3) = 20;
|
||||
e.Get(2,0) = 31; e.Get(2,1) = 32; e.Get(2,2) = 33; e.Get(2,3) = 30;
|
||||
e.Get(3,0) = 41; e.Get(3,1) = 42; e.Get(3,2) = 43; e.Get(3,3) = 40;
|
||||
|
||||
// Exercise
|
||||
a.ShiftColumnsLeftInplace();
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == e);
|
||||
}
|
||||
|
||||
// Tests that ShiftColumnsLeftInplace()() does the exact same thing as ShiftColumnsLeft()
|
||||
TEST_CASE(__FILE__"/shift-columns-left-same-as-inplace", "[Block]") {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
const Block initial_a = a;
|
||||
|
||||
// Exercise and verify
|
||||
a.ShiftColumnsLeftInplace();
|
||||
REQUIRE(a == initial_a.ShiftColumnsLeft());
|
||||
}
|
||||
|
||||
// Tests that shift columns right works
|
||||
TEST_CASE(__FILE__"/shift-columns-right", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block a;
|
||||
a.Get(0,0) = 10; a.Get(0,1) = 11; a.Get(0,2) = 12; a.Get(0,3) = 13;
|
||||
a.Get(1,0) = 20; a.Get(1,1) = 21; a.Get(1,2) = 22; a.Get(1,3) = 23;
|
||||
a.Get(2,0) = 30; a.Get(2,1) = 31; a.Get(2,2) = 32; a.Get(2,3) = 33;
|
||||
a.Get(3,0) = 40; a.Get(3,1) = 41; a.Get(3,2) = 42; a.Get(3,3) = 43;
|
||||
|
||||
Block e; /* expected */
|
||||
e.Get(0,0) = 13; e.Get(0,1) = 10; e.Get(0,2) = 11; e.Get(0,3) = 12;
|
||||
e.Get(1,0) = 23; e.Get(1,1) = 20; e.Get(1,2) = 21; e.Get(1,3) = 22;
|
||||
e.Get(2,0) = 33; e.Get(2,1) = 30; e.Get(2,2) = 31; e.Get(2,3) = 32;
|
||||
e.Get(3,0) = 43; e.Get(3,1) = 40; e.Get(3,2) = 41; e.Get(3,3) = 42;
|
||||
|
||||
// Exercise
|
||||
a.ShiftColumnsRightInplace();
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == e);
|
||||
}
|
||||
|
||||
// Tests that ShiftColumnsRightInplace()() does the exact same thing as ShiftColumnsRight()
|
||||
TEST_CASE(__FILE__"/shift-columns-right-same-as-inplace", "[Block]") {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
const Block initial_a = a;
|
||||
|
||||
// Exercise and verify
|
||||
a.ShiftColumnsRightInplace();
|
||||
REQUIRE(a == initial_a.ShiftColumnsRight());
|
||||
}
|
||||
|
||||
// Tests that shift cells left works
|
||||
TEST_CASE(__FILE__"/shift-cells-left", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block a;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
a.Get(i) = i;
|
||||
}
|
||||
|
||||
Block expected;
|
||||
for (std::size_t i = 0; i < 15; i++) {
|
||||
expected.Get(i) = i+1;
|
||||
}
|
||||
expected.Get(15) = 0;
|
||||
|
||||
// Exercise
|
||||
a.ShiftCellsLeftInplace();
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == expected);
|
||||
}
|
||||
|
||||
// Tests that ShiftCellsLeftInplace()() does the exact same thing as ShiftCellsLeft()
|
||||
TEST_CASE(__FILE__"/shift-cells-left-same-as-inplace", "[Block]") {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
const Block initial_a = a;
|
||||
|
||||
// Exercise and verify
|
||||
a.ShiftCellsLeftInplace();
|
||||
REQUIRE(a == initial_a.ShiftCellsLeft());
|
||||
}
|
||||
|
||||
// Tests that shift cells right works
|
||||
TEST_CASE(__FILE__"/shift-cells-right", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block a;
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
a.Get(i) = i;
|
||||
}
|
||||
|
||||
Block expected;
|
||||
for (std::size_t i = 1; i < 16; i++) {
|
||||
expected.Get(i) = i-1;
|
||||
}
|
||||
expected.Get(0) = 15;
|
||||
|
||||
// Exercise
|
||||
a.ShiftCellsRightInplace();
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == expected);
|
||||
}
|
||||
|
||||
// Tests that ShiftCellsRightInplace()() does the exact same thing as ShiftCellsRight()
|
||||
TEST_CASE(__FILE__"/shift-cells-right-same-as-inplace", "[Block]") {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
const Block initial_a = a;
|
||||
|
||||
// Exercise and verify
|
||||
a.ShiftCellsRightInplace();
|
||||
REQUIRE(a == initial_a.ShiftCellsRight());
|
||||
}
|
||||
|
||||
// Tests that shifting down undoes shifting up, and vica versa
|
||||
TEST_CASE(__FILE__"/shift-down-undoes-shift-up", "[Block]") {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
const Block initial_a = a;
|
||||
|
||||
// Exercise
|
||||
a.ShiftRowsUpInplace();
|
||||
a.ShiftRowsDownInplace();
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == initial_a);
|
||||
}
|
||||
|
||||
// Tests that shifting left undoes shifting right, and vica versa
|
||||
TEST_CASE(__FILE__"/shift-left-undoes-shift-right", "[Block]") {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
const Block initial_a = a;
|
||||
|
||||
// Exercise
|
||||
a.ShiftColumnsRightInplace();
|
||||
a.ShiftColumnsLeftInplace();
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == initial_a);
|
||||
}
|
||||
|
||||
// Tests that shifting cells left undoes shifting cells right, and vica versa
|
||||
TEST_CASE(__FILE__"/cellshift-left-undoes-cellshift-right", "[Block]") {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
const Block initial_a = a;
|
||||
|
||||
// Exercise
|
||||
a.ShiftCellsRightInplace();
|
||||
a.ShiftCellsLeftInplace();
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == initial_a);
|
||||
}
|
||||
|
||||
// Tests that multiple, combined shifts and additions can be undone
|
||||
TEST_CASE(__FILE__"/multiple-combined-shifts-and-additions-can-be-undone", "[Block]") {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
Block key = Key::FromPassword("Papaya");
|
||||
|
||||
const Block initial_a = a;
|
||||
|
||||
// Exercise (mix-up)
|
||||
for (std::size_t i = 0; i < 64; i++) {
|
||||
a.ShiftRowsUpInplace();
|
||||
a.ShiftColumnsLeftInplace();
|
||||
a += key;
|
||||
a.ShiftCellsRightInplace();
|
||||
}
|
||||
|
||||
// Exercise (un-mix)
|
||||
for (std::size_t i = 0; i < 64; i++) {
|
||||
a.ShiftCellsLeftInplace();
|
||||
a -= key;
|
||||
a.ShiftColumnsRightInplace();
|
||||
a.ShiftRowsDownInplace();
|
||||
}
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == initial_a);
|
||||
}
|
||||
|
||||
// Tests that the get-bit method works
|
||||
TEST_CASE(__FILE__"/get-bit", "[Block]") {
|
||||
for (std::size_t i = 0; i < 100; i++) {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
|
||||
// Exercise
|
||||
std::stringstream ss;
|
||||
for (std::size_t i = 0; i < 512; i++) {
|
||||
ss << a.GetBit(i);
|
||||
}
|
||||
|
||||
// Verify
|
||||
REQUIRE(ss.str() == a.ToBinaryString());
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that the set-bit method works
|
||||
TEST_CASE(__FILE__"/set-bit", "[Block]") {
|
||||
for (std::size_t i = 0; i < 100; i++) {
|
||||
// Setup
|
||||
const std::string a_bits = Key::Random().ToBinaryString();
|
||||
|
||||
// Exercise
|
||||
Block a;
|
||||
for (std::size_t i = 0; i < 512; i++) {
|
||||
a.SetBit(i, a_bits[i] == '1');
|
||||
}
|
||||
|
||||
// Verify
|
||||
REQUIRE(a_bits == a.ToBinaryString());
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that the set-bit to-false method works
|
||||
TEST_CASE(__FILE__"/set-bit-to-false", "[Block]") {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
|
||||
// Exercise
|
||||
a.SetBit(5, 0);
|
||||
a.SetBit(15, 0);
|
||||
a.SetBit(105, 0);
|
||||
a.SetBit(205, 0);
|
||||
|
||||
// Verify
|
||||
REQUIRE(a.GetBit(5) == false);
|
||||
REQUIRE(a.GetBit(15) == false);
|
||||
REQUIRE(a.GetBit(105) == false);
|
||||
REQUIRE(a.GetBit(205) == false);
|
||||
}
|
||||
|
||||
// Tests that the set-bit to-true method works
|
||||
TEST_CASE(__FILE__"/set-bit-to-true", "[Block]") {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
|
||||
// Exercise
|
||||
a.SetBit(5, 1);
|
||||
a.SetBit(15, 1);
|
||||
a.SetBit(105, 1);
|
||||
a.SetBit(205, 1);
|
||||
|
||||
// Verify
|
||||
REQUIRE(a.GetBit(5) == true);
|
||||
REQUIRE(a.GetBit(15) == true);
|
||||
REQUIRE(a.GetBit(105) == true);
|
||||
REQUIRE(a.GetBit(205) == true);
|
||||
}
|
||||
|
||||
// Tests that the flip-bit method works
|
||||
TEST_CASE(__FILE__"/flip-bit", "[Block]") {
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
|
||||
std::string compare = a.ToBinaryString();
|
||||
compare[5] = compare[5] == '1' ? '0' : '1';
|
||||
compare[15] = compare[15] == '1' ? '0' : '1';
|
||||
compare[105] = compare[105] == '1' ? '0' : '1';
|
||||
compare[205] = compare[205] == '1' ? '0' : '1';
|
||||
|
||||
// Exercise
|
||||
a.FlipBit(5);
|
||||
a.FlipBit(15);
|
||||
a.FlipBit(105);
|
||||
a.FlipBit(205);
|
||||
|
||||
// Verify
|
||||
REQUIRE(a.ToBinaryString() == compare);
|
||||
}
|
||||
|
||||
// Tests that bitshifts (to the left) work
|
||||
TEST_CASE(__FILE__"/bitshift-left", "[Block]") {
|
||||
|
||||
// Setup
|
||||
srand(time(0));
|
||||
std::stringstream ss;
|
||||
|
||||
for (std::size_t i = 0; i < 512; i++) {
|
||||
ss << (rand()%2 == 0 ? '1' : '0');
|
||||
}
|
||||
const std::string originalBits = ss.str();
|
||||
ss.str("");
|
||||
|
||||
// Shift string manually
|
||||
std::string shiftedBits = originalBits;
|
||||
shiftedBits.erase(0, 1);
|
||||
ss << shiftedBits << originalBits[0];
|
||||
shiftedBits = ss.str();
|
||||
|
||||
// Create block of original bits
|
||||
Block block(originalBits);
|
||||
|
||||
// Exercise
|
||||
block = block.ShiftBitsLeft();
|
||||
|
||||
// Verify
|
||||
REQUIRE(block.ToBinaryString().length() == shiftedBits.length());
|
||||
REQUIRE(block.ToBinaryString() == shiftedBits);
|
||||
}
|
||||
|
||||
// Tests that inplace-bitshifts to the left do the exact same as copy bitshifts
|
||||
TEST_CASE(__FILE__"/bitshift-left-inplace", "[Block]") {
|
||||
|
||||
// Setup
|
||||
srand(time(0));
|
||||
std::stringstream ss;
|
||||
|
||||
for (std::size_t i = 0; i < 512; i++) {
|
||||
ss << (rand()%2 == 0 ? '1' : '0');
|
||||
}
|
||||
Block a(ss.str());
|
||||
|
||||
// Exercise
|
||||
Block b = a.ShiftBitsLeft();
|
||||
a.ShiftBitsLeftInplace();
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == b);
|
||||
}
|
||||
|
||||
// Tests that bitshifts (to the right) work
|
||||
TEST_CASE(__FILE__"/bitshift-right", "[Block]") {
|
||||
|
||||
// Setup
|
||||
srand(time(0));
|
||||
std::stringstream ss;
|
||||
|
||||
for (std::size_t i = 0; i < 512; i++) {
|
||||
ss << (rand()%2 == 0 ? '1' : '0');
|
||||
}
|
||||
const std::string originalBits = ss.str();
|
||||
ss.str("");
|
||||
|
||||
// Shift string manually
|
||||
std::string shiftedBits = originalBits;
|
||||
shiftedBits.erase(shiftedBits.length() - 1);
|
||||
ss << originalBits[originalBits.length()-1] << shiftedBits;
|
||||
shiftedBits = ss.str();
|
||||
|
||||
// Create block of original bits
|
||||
Block block(originalBits);
|
||||
|
||||
// Exercise
|
||||
block = block.ShiftBitsRight();
|
||||
|
||||
// Verify
|
||||
REQUIRE(block.ToBinaryString().length() == shiftedBits.length());
|
||||
REQUIRE(block.ToBinaryString() == shiftedBits);
|
||||
}
|
||||
|
||||
// Tests that inplace-bitshifts to the right do the exact same as copy bitshifts
|
||||
TEST_CASE(__FILE__"/bitshift-right-inplace", "[Block]") {
|
||||
|
||||
// Setup
|
||||
srand(time(0));
|
||||
std::stringstream ss;
|
||||
|
||||
for (std::size_t i = 0; i < 512; i++) {
|
||||
ss << (rand()%2 == 0 ? '1' : '0');
|
||||
}
|
||||
Block a(ss.str());
|
||||
|
||||
// Exercise
|
||||
Block b = a.ShiftBitsRight();
|
||||
a.ShiftBitsRightInplace();
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == b);
|
||||
}
|
||||
|
||||
// Tests that bitshifting undoes itself
|
||||
TEST_CASE(__FILE__"/bitshifting-undoes-itself", "[Block]") {
|
||||
|
||||
// Setup
|
||||
Block a = Key::Random();
|
||||
|
||||
const Block initial_a = a;
|
||||
|
||||
// Exercise (mix-up)
|
||||
for (std::size_t i = 0; i < 100; i++) {
|
||||
a.ShiftBitsLeftInplace();
|
||||
}
|
||||
|
||||
// Exercise (un-mix)
|
||||
for (std::size_t i = 0; i < 100; i++) {
|
||||
a.ShiftBitsRightInplace();
|
||||
}
|
||||
|
||||
// Verify
|
||||
REQUIRE(a == initial_a);
|
||||
}
|
||||
|
17965
GCryptLib/test/Catch2.h
@ -1,87 +0,0 @@
|
||||
#include <GCrypt/GWrapper.h>
|
||||
#include <GCrypt/Util.h>
|
||||
#include "Catch2.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
// THESE TESTS ASSUME BLOCK_SIZE == 512
|
||||
|
||||
// Tests that encrypting a message of exactly BLOCK_SIZE yields the exact message back
|
||||
TEST_CASE(__FILE__"/SingleBlock", "[Encryption/Decryption consistency]") {
|
||||
|
||||
// Instanciate our cipher and supply a key
|
||||
const Key key = Key::FromPassword("1234");
|
||||
|
||||
// Recode the ascii-string to bits
|
||||
const std::string cleartext_bits =
|
||||
"1011110011010110000010110001111000111010111101001010100100011101"
|
||||
"0101110101010010100000110100001000011000111010001001110101111111"
|
||||
"1110110101100101110001010101011110001010000010111110011011010111"
|
||||
"1100110100111000000011100101010100110010001110010011000010111001"
|
||||
"0000010000010000011001111010011110111001000000000110101000110001"
|
||||
"0110111110110110100000010100000011010001000011100100111001001011"
|
||||
"1101100100000100010000001011100010010001101111100100101100010001"
|
||||
"0000011110010110111010110110111110011110011010001100100111110101";
|
||||
|
||||
std::vector<Block> cleartext_blocks({Block(cleartext_bits)});
|
||||
|
||||
// Encrypt our cleartext bits
|
||||
const std::vector<Block> ciphertext_blocks = GWrapper::CipherBlocks(cleartext_blocks, key, GCipher::DIRECTION::ENCIPHER);
|
||||
|
||||
// Decipher it again
|
||||
const std::vector<Block> decrypted_blocks = GWrapper::CipherBlocks(ciphertext_blocks, key, GCipher::DIRECTION::DECIPHER);
|
||||
|
||||
// Assert that the decrypted text equals the plaintext
|
||||
REQUIRE(
|
||||
cleartext_blocks ==
|
||||
decrypted_blocks
|
||||
);
|
||||
}
|
||||
|
||||
// Tests that a decrypted ciphertext equals its plaintext version, using a cleartext that requires A LOT of blocks
|
||||
TEST_CASE(__FILE__"MultiBlock_NoPadding/", "[Encryption/Decryption consistency]") {
|
||||
|
||||
// Instanciate our cipher and supply a key
|
||||
const Key key = Key::FromPassword("1234");
|
||||
|
||||
std::stringstream ss;
|
||||
const std::string charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
// Read 10 blocks worth of characters
|
||||
srand(time(0));
|
||||
for (std::size_t i = 0; i < 512*10; i++) {
|
||||
ss << charset[rand() % charset.length()];
|
||||
}
|
||||
const std::string cleartext_str = ss.str();
|
||||
|
||||
std::vector<Block> cleartext_blocks = StringToBitblocks(cleartext_str);
|
||||
|
||||
// Encrypt our cleartext bits
|
||||
std::vector<Block> ciphertext_blocks;
|
||||
ciphertext_blocks.reserve(cleartext_blocks.size());
|
||||
{
|
||||
GCipher cipher(key, GCipher::DIRECTION::ENCIPHER);
|
||||
|
||||
for (const Block& clearBlock : cleartext_blocks) {
|
||||
ciphertext_blocks.emplace_back(cipher.Digest(clearBlock));
|
||||
}
|
||||
}
|
||||
|
||||
// Decipher it again
|
||||
std::vector<Block> deciphered_blocks;
|
||||
deciphered_blocks.reserve(ciphertext_blocks.size());
|
||||
{
|
||||
GCipher cipher(key, GCipher::DIRECTION::DECIPHER);
|
||||
|
||||
for (const Block& ciphBlock : ciphertext_blocks) {
|
||||
deciphered_blocks.emplace_back(cipher.Digest(ciphBlock));
|
||||
}
|
||||
}
|
||||
|
||||
// Assert that the decrypted text equals the plaintext
|
||||
REQUIRE(
|
||||
cleartext_blocks ==
|
||||
deciphered_blocks
|
||||
);
|
||||
}
|
||||
|
@ -1,86 +0,0 @@
|
||||
#include <GCrypt/GWrapper.h>
|
||||
#include <GCrypt/Util.h>
|
||||
#include "Catch2.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
// Tests that encrypting and decrypting short strings using the wrapper works.
|
||||
// This test will start from scratch after encryption, to ensure EVERYTHING has to be re-calculated.
|
||||
TEST_CASE(__FILE__"/Encrypting and decrypting strings works, Single block", "[Wrapper]") {
|
||||
|
||||
// Setup
|
||||
const std::string plaintext = "Hello, World!";
|
||||
const Key key = Key::FromPassword("Der Affe will Zucker");
|
||||
|
||||
std::string ciphertext;
|
||||
std::string decrypted;
|
||||
|
||||
// Encryption
|
||||
ciphertext = GWrapper::EncryptString(plaintext, key);
|
||||
|
||||
// Decryption
|
||||
decrypted = GWrapper::DecryptString(ciphertext, key);
|
||||
|
||||
// Assertion
|
||||
REQUIRE(plaintext == decrypted);
|
||||
}
|
||||
|
||||
// Tests that encrypting and decrypting very long strings using the wrapper works.
|
||||
// This test will start from scratch after encryption, to ensure EVERYTHING has to be re-calculated.
|
||||
TEST_CASE(__FILE__"/Encrypting and decrypting strings works, Many blocks block", "[Wrapper]") {
|
||||
|
||||
// Setup
|
||||
|
||||
// Read an not-multiple-of-blocksize amount of random chars, that's very large (about 200kb long string)
|
||||
srand(time(0));
|
||||
|
||||
std::stringstream ss;
|
||||
const std::string charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
for (std::size_t i = 0; i < 198273; i++) {
|
||||
ss << charset[rand() % charset.length()];
|
||||
}
|
||||
|
||||
const std::string plaintext = ss.str();
|
||||
const Key key = Key::FromPassword("Der Affe will Zucker");
|
||||
|
||||
std::string ciphertext;
|
||||
std::string decrypted;
|
||||
|
||||
// Encryption
|
||||
ciphertext = GWrapper::EncryptString(plaintext, key);
|
||||
|
||||
// Decryption
|
||||
decrypted = GWrapper::DecryptString(ciphertext, key);
|
||||
|
||||
// Assertion
|
||||
REQUIRE(plaintext == decrypted);
|
||||
}
|
||||
|
||||
// Tests that encrypting and decrypting files using the wrapper works.
|
||||
// This test will start from scratch after encryption, to ensure EVERYTHING has to be re-calculated.
|
||||
TEST_CASE(__FILE__"/Encrypting and decrypting files works", "[Wrapper]") {
|
||||
|
||||
// Setup
|
||||
const std::string testfile_dir = "testAssets/";
|
||||
|
||||
const std::string filename_plain = testfile_dir + "testfile.png";
|
||||
const std::string filename_encrypted = testfile_dir + "testfile.png.crypt";
|
||||
const std::string filename_decrypted = testfile_dir + "testfile.png.clear.png";
|
||||
const Key key = Key::FromPassword("Der Affe will Zucker");
|
||||
|
||||
|
||||
// Encryption
|
||||
GWrapper::EncryptFile(filename_plain, filename_encrypted, key);
|
||||
|
||||
// Decryption
|
||||
GWrapper::DecryptFile(filename_encrypted, filename_decrypted, key);
|
||||
|
||||
// Read in both the base, and the decrypted file
|
||||
const std::vector<Block> plainfile = ReadFileToBlocks(filename_plain);
|
||||
const std::vector<Block> decryptfile = ReadFileToBlocks(filename_decrypted);
|
||||
|
||||
// Assertion (If this fails, maybe check if the image is even readable by an image viewer)
|
||||
REQUIRE(plainfile.size() == decryptfile.size());
|
||||
REQUIRE(plainfile == decryptfile);
|
||||
}
|
||||
|
@ -1,94 +0,0 @@
|
||||
#include <GCrypt/Util.h>
|
||||
#include <GCrypt/Block.h>
|
||||
#include <GCrypt/Config.h>
|
||||
#include <unordered_map>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include "Catch2.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
// We can generate passwords by just translating a decimal number to base "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
// So this is just a helper function to generate random passwords
|
||||
inline std::string Base10_2_X(const unsigned long long int i, const std::string set, unsigned int padding) {
|
||||
if (set.length() == 0)
|
||||
return ""; // Return empty string, if set is empty. Play stupid games, win stupid prizes.
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
if (i != 0) {
|
||||
{
|
||||
unsigned long long int buf = i;
|
||||
while (buf != 0) {
|
||||
const unsigned long long int mod = buf % set.length();
|
||||
buf /= set.length();
|
||||
ss << set[(std::size_t)mod];
|
||||
}
|
||||
}
|
||||
{
|
||||
const std::string buf = ss.str();
|
||||
ss.str("");
|
||||
for (long long int i = buf.length() - 1; i >= 0; i--) {
|
||||
ss << buf[(std::size_t)i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ss << set[0]; // If i is 0, just pass a null-value. The algorithm would hang otherwise.
|
||||
}
|
||||
|
||||
// Add as much null-values to the left as requested.
|
||||
if (ss.str().length() < padding) {
|
||||
const std::size_t cachedLen = ss.str().length();
|
||||
const std::string cachedStr = ss.str();
|
||||
ss.str("");
|
||||
for (std::size_t i = 0; i < padding - cachedLen; i++) {
|
||||
ss << set[0];
|
||||
}
|
||||
ss << cachedStr;
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Run a few thousand random passwords through the keygen and see if we'll find a collision.
|
||||
// This test passing does NOT mean that it's resistant! Maybe good, maybe shit! But if it fails, it's definitely shit.
|
||||
// Already validated range: Password 0 - 1.000.000
|
||||
TEST_CASE(__FILE__"/Password to key transformation collision resistance", "[Key extrapolation]") {
|
||||
|
||||
// To test resistence set this to a high number around a million.
|
||||
// This will take a LONG while to execute though (about 2.5hrs on my machine), hence why it's set so low.
|
||||
constexpr std::size_t NUM_RUN_TESTS = 10;
|
||||
|
||||
std::unordered_map<std::string, std::string> keys; // <key, password>
|
||||
|
||||
// Try NUM_RUN_TESTS passwords
|
||||
const std::string charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
for (std::size_t i = 0; i < NUM_RUN_TESTS; i++) {
|
||||
// Get password
|
||||
const std::string password = Base10_2_X(i, charset, 0);
|
||||
|
||||
// Generate key
|
||||
const std::string newKeyBits = Key::FromPassword(password).ToBinaryString();
|
||||
|
||||
// Check if this block is already in our map
|
||||
if (keys.find(newKeyBits) != keys.cend()) {
|
||||
std::cout << "Collision found between password \""
|
||||
<< password
|
||||
<< "\" and \""
|
||||
<< keys[newKeyBits]
|
||||
<< "\". The key is \""
|
||||
<< newKeyBits
|
||||
<< "\".";
|
||||
|
||||
FAIL();
|
||||
}
|
||||
|
||||
// All good? Insert it into our map
|
||||
keys[newKeyBits] = password;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1,2 +0,0 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "Catch2.h"
|
Before Width: | Height: | Size: 9.5 KiB |
@ -1,51 +0,0 @@
|
||||
#!zsh
|
||||
|
||||
echo "Make sure to have run all visualization executables in ../build/ (cmake -B build)!"
|
||||
echo "These generate the base images!"
|
||||
|
||||
# Copy all images over, but as pngs, and a bit larger
|
||||
find ../build/ -maxdepth 1 -type f -name '*.bmp' |\
|
||||
xargs -I {}\
|
||||
convert "{}"\
|
||||
-filter box\
|
||||
-resize 256x\
|
||||
"{}.png"
|
||||
|
||||
mv ../build/*.png .
|
||||
|
||||
# Create a few gifs
|
||||
|
||||
# Singleblock diffusion
|
||||
convert -delay 10 -loop 0 -dispose previous \
|
||||
"visualize-singleblock-diffusion-input.bmp.png"\
|
||||
"visualize-singleblock-diffusion-input-flip.bmp.png"\
|
||||
"visualize-singleblock-diffusion-input.gif"
|
||||
|
||||
convert -delay 10 -loop 0 -dispose previous \
|
||||
"visualize-singleblock-diffusion-output.bmp.png"\
|
||||
"visualize-singleblock-diffusion-output-flip.bmp.png"\
|
||||
"visualize-singleblock-diffusion-output.gif"
|
||||
|
||||
|
||||
# Multiblock diffusion
|
||||
convert -delay 10 -loop 0 -dispose previous \
|
||||
"visualize-multiblock-diffusion-input.bmp.png"\
|
||||
"visualize-multiblock-diffusion-input-flip.bmp.png"\
|
||||
"visualize-multiblock-diffusion-input.gif"
|
||||
|
||||
convert -delay 10 -loop 0 -dispose previous \
|
||||
"visualize-multiblock-diffusion-output.bmp.png"\
|
||||
"visualize-multiblock-diffusion-output-flip.bmp.png"\
|
||||
"visualize-multiblock-diffusion-output.gif"
|
||||
|
||||
# Extreme input diffusion
|
||||
convert -delay 10 -loop 0 -dispose previous \
|
||||
"visualize-extreme-input-diffusion-input.bmp.png"\
|
||||
"visualize-extreme-input-diffusion-input-flip.bmp.png"\
|
||||
"visualize-extreme-input-diffusion-input.gif"
|
||||
|
||||
convert -delay 10 -loop 0 -dispose previous \
|
||||
"visualize-extreme-input-diffusion-output.bmp.png"\
|
||||
"visualize-extreme-input-diffusion-output-flip.bmp.png"\
|
||||
"visualize-extreme-input-diffusion-output.gif"
|
||||
|
Before Width: | Height: | Size: 335 B |
Before Width: | Height: | Size: 324 B |
Before Width: | Height: | Size: 908 B |
Before Width: | Height: | Size: 314 B |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 357 B |
Before Width: | Height: | Size: 358 B |
Before Width: | Height: | Size: 451 B |
Before Width: | Height: | Size: 448 B |