Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
76c0050d60 | |||
08aaf69262 | |||
b78338dccc | |||
d0deac3a65 | |||
ebba9f591e | |||
fb5d990421 | |||
d2644c0d04 | |||
d7f741c28c | |||
2505493534 | |||
aaecd43e2d | |||
cc3f9da1d2 |
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,7 +1,11 @@
|
|||||||
*.html
|
*.html
|
||||||
*.user
|
*.user
|
||||||
|
/**/.settings
|
||||||
|
/**/.vs
|
||||||
/**/bin
|
/**/bin
|
||||||
|
/**/dist
|
||||||
|
/**/doc
|
||||||
/**/lib
|
/**/lib
|
||||||
/**/obj
|
/**/obj
|
||||||
/.vs
|
/**/out
|
||||||
/out
|
/**/target
|
||||||
|
48
Makefile
48
Makefile
@ -6,13 +6,20 @@ DEBUG ?= 0
|
|||||||
NALYZE ?= 0
|
NALYZE ?= 0
|
||||||
ASAN ?= 0
|
ASAN ?= 0
|
||||||
STATIC ?= 0
|
STATIC ?= 0
|
||||||
|
SHARED ?= 0
|
||||||
FLTO ?= 0
|
FLTO ?= 0
|
||||||
FPGO ?= 0
|
FPGO ?= 0
|
||||||
STRIP ?= 0
|
STRIP ?= 0
|
||||||
CPU ?= 0
|
CPU ?= 0
|
||||||
THREAD ?= 1
|
THREAD ?= 1
|
||||||
|
|
||||||
$(info Options: DEBUG=$(DEBUG), NALYZE=$(NALYZE), ASAN=$(ASAN), STATIC=$(STATIC), FLTO=$(FLTO), FPGO=$(FPGO), STRIP=$(STRIP), CPU=$(CPU), THREAD=$(THREAD))
|
$(info Options: DEBUG=$(DEBUG), NALYZE=$(NALYZE), ASAN=$(ASAN), STATIC=$(STATIC), SHARED=$(SHARED), FLTO=$(FLTO), FPGO=$(FPGO), STRIP=$(STRIP), CPU=$(CPU), THREAD=$(THREAD))
|
||||||
|
|
||||||
|
ifneq ($(SHARED),0)
|
||||||
|
ifneq ($(STATIC),0)
|
||||||
|
$(error Options SHARED=1 and STATIC=1 are mutually exclusive!)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Directories
|
# Directories
|
||||||
@ -72,6 +79,9 @@ endif
|
|||||||
|
|
||||||
ifneq (,$(firstword $(filter %mingw32 %-windows-gnu %-cygwin %-cygnus,$(MACHINE))))
|
ifneq (,$(firstword $(filter %mingw32 %-windows-gnu %-cygwin %-cygnus,$(MACHINE))))
|
||||||
EXE_SUFFIX := .exe
|
EXE_SUFFIX := .exe
|
||||||
|
LIB_SUFFIX := .$(if $(subst 0,,$(SHARED)),dll,a)
|
||||||
|
else
|
||||||
|
LIB_SUFFIX := .$(if $(subst 0,,$(SHARED)),$(if $(findstring -apple-darwin,$(MACHINE)),dylib,so),a)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq (,$(firstword $(filter %-w64-mingw32 %w64-windows-gnu,$(MACHINE))))
|
ifneq (,$(firstword $(filter %-w64-mingw32 %w64-windows-gnu,$(MACHINE))))
|
||||||
@ -96,12 +106,26 @@ ifneq (,$(firstword $(filter %-pc-haiku %-unknown-haiku,$(MACHINE))))
|
|||||||
LDFLGS += -lbsd
|
LDFLGS += -lbsd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
APP_CFLAGS = $(CFLAGS)
|
||||||
|
APP_LDFLGS = -L$(SUBDIR_LIB)/lib -l$(VERSION_LIB) $(LDFLGS)
|
||||||
|
LIB_CFLAGS = $(CFLAGS)
|
||||||
|
LIB_LDFLGS = $(LDFLGS)
|
||||||
|
|
||||||
|
ifneq ($(SHARED),0)
|
||||||
|
LIB_CFLAGS += -fPIC
|
||||||
|
ifneq (,$(firstword $(filter %-w64-mingw32 %w64-windows-gnu,$(MACHINE))))
|
||||||
|
LIB_LDFLGS = -Wl,--out-implib,"$@.a" $(LDFLGS)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# File names
|
# File names
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
VERSION_LIB := slunkcrypt$(CONFIG)-1
|
||||||
|
|
||||||
OUTNAME_APP := slunkcrypt$(CONFIG)$(EXE_SUFFIX)
|
OUTNAME_APP := slunkcrypt$(CONFIG)$(EXE_SUFFIX)
|
||||||
OUTNAME_LIB := libslunkcrypt$(CONFIG)-1.a
|
OUTNAME_LIB := lib$(VERSION_LIB)$(LIB_SUFFIX)
|
||||||
|
|
||||||
OUTPATH_APP := $(SUBDIR_APP)/bin/$(OUTNAME_APP)
|
OUTPATH_APP := $(SUBDIR_APP)/bin/$(OUTNAME_APP)
|
||||||
OUTPATH_LIB := $(SUBDIR_LIB)/lib/$(OUTNAME_LIB)
|
OUTPATH_LIB := $(SUBDIR_LIB)/lib/$(OUTNAME_LIB)
|
||||||
@ -121,21 +145,27 @@ endif
|
|||||||
# Targets
|
# Targets
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all build clean
|
||||||
|
|
||||||
all: $(OUTPATH_APP)
|
all: clean build
|
||||||
|
|
||||||
|
build: $(OUTPATH_APP)
|
||||||
|
|
||||||
$(OUTPATH_APP): $(OBJECTS_APP) $(OUTPATH_LIB)
|
$(OUTPATH_APP): $(OBJECTS_APP) $(OUTPATH_LIB)
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
$(CC) $(CFLAGS) $^ -o $@ $(LDFLGS)
|
$(CC) $(APP_CFLAGS) $(OBJECTS_APP) -o $@ $(APP_LDFLGS)
|
||||||
|
|
||||||
$(OUTPATH_LIB): $(OBJECTS_LIB)
|
$(OUTPATH_LIB): $(OBJECTS_LIB)
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
|
ifneq ($(SHARED),0)
|
||||||
|
$(CC) $(LIB_CFLAGS) $^ -shared -o $@ $(LIB_LDFLGS)
|
||||||
|
else
|
||||||
$(AR) rcs $@ $^
|
$(AR) rcs $@ $^
|
||||||
|
endif
|
||||||
|
|
||||||
$(SUBDIR_APP)/obj/%$(CONFIG).o: $(SUBDIR_APP)/src/%.c
|
$(SUBDIR_APP)/obj/%$(CONFIG).o: $(SUBDIR_APP)/src/%.c
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(APP_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
$(SUBDIR_APP)/obj/%.rsrc.o: $(SUBDIR_APP)/res/%.rc
|
$(SUBDIR_APP)/obj/%.rsrc.o: $(SUBDIR_APP)/res/%.rc
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
@ -143,8 +173,8 @@ $(SUBDIR_APP)/obj/%.rsrc.o: $(SUBDIR_APP)/res/%.rc
|
|||||||
|
|
||||||
$(SUBDIR_LIB)/obj/%$(CONFIG).o: $(SUBDIR_LIB)/src/%.c
|
$(SUBDIR_LIB)/obj/%$(CONFIG).o: $(SUBDIR_LIB)/src/%.c
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(LIB_CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) $(SUBDIR_APP)/obj/*.o $(SUBDIR_APP)/obj/*.gcda $(SUBDIR_APP)/lib/*.a $(SUBDIR_APP)/bin/*$(EXE_SUFFIX)
|
$(RM) $(SUBDIR_APP)/obj/* $(SUBDIR_APP)/lib/* $(SUBDIR_APP)/bin/*
|
||||||
$(RM) $(SUBDIR_LIB)/obj/*.o $(SUBDIR_LIB)/obj/*.gcda $(SUBDIR_LIB)/lib/*.a $(SUBDIR_LIB)/bin/*$(EXE_SUFFIX)
|
$(RM) $(SUBDIR_LIB)/obj/* $(SUBDIR_LIB)/lib/* $(SUBDIR_LIB)/bin/*
|
||||||
|
@ -63,6 +63,9 @@ The following settings can be adjusted in the `slunkcrypt-gui.exe.config` config
|
|||||||
- **`KeepIncompleteFiles`:**
|
- **`KeepIncompleteFiles`:**
|
||||||
If set to `true`, incomplete or corrupted output files will *not* be deleted — default value: `false`.
|
If set to `true`, incomplete or corrupted output files will *not* be deleted — default value: `false`.
|
||||||
|
|
||||||
|
- **`LegacyCompat`:**
|
||||||
|
If set to `1`, show options to enable “legacy” compatibility-mode in the GUI; if set to `2`, select “legacy” compatibility-mode by default — default value: `0`.
|
||||||
|
|
||||||
Command-line Usage
|
Command-line Usage
|
||||||
==================
|
==================
|
||||||
|
|
||||||
@ -132,7 +135,7 @@ The following environment variables may be used:
|
|||||||
Specifies the number of worker threads to use. By default, SlunkCrypt detects the number of available processors and creates one thread for each processor.
|
Specifies the number of worker threads to use. By default, SlunkCrypt detects the number of available processors and creates one thread for each processor.
|
||||||
|
|
||||||
- **`SLUNK_LEGACY_COMPAT`**:
|
- **`SLUNK_LEGACY_COMPAT`**:
|
||||||
If set to a *non-zero* value, enables "legacy" compatibility-mode, required to decrypt files encrypted with SlunkCrypt version 1.2.x or older.
|
If set to a *non-zero* value, enables “legacy” compatibility-mode, required to decrypt files encrypted with SlunkCrypt version 1.2.x or older.
|
||||||
|
|
||||||
- **`SLUNK_DEBUG_LOGGING`**:
|
- **`SLUNK_DEBUG_LOGGING`**:
|
||||||
If set to a *non-zero* value, enables additional logging output to the syslog (Unix-like) or to the debugger (Windows). This is intended for debugging purposes only!
|
If set to a *non-zero* value, enables additional logging output to the syslog (Unix-like) or to the debugger (Windows). This is intended for debugging purposes only!
|
||||||
|
17
binding/java/.classpath
Normal file
17
binding/java/.classpath
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="src" output="tests/bin" path="tests/src">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="test" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="con" path="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=SlunkCrypt&ivyXmlPath=ivy.xml&confs=*"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="test" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
18
binding/java/.project
Normal file
18
binding/java/.project
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>SlunkCrypt</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
<nature>org.apache.ivyde.eclipse.ivynature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
73
binding/java/build.xml
Normal file
73
binding/java/build.xml
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<project xmlns:ivy="antlib:org.apache.ivy.ant" name="SlunkCrypt" default="default" basedir=".">
|
||||||
|
<property name="bin.dir" location="bin"/>
|
||||||
|
<property name="doc.dir" location="doc"/>
|
||||||
|
<property name="lib.dir" location="lib"/>
|
||||||
|
<property name="out.dir" location="out"/>
|
||||||
|
<property name="src.dir" location="src"/>
|
||||||
|
<property name="test.src.dir" location="tests/src"/>
|
||||||
|
<property name="test.bin.dir" location="tests/bin"/>
|
||||||
|
<property name="test.out.dir" location="tests/out"/>
|
||||||
|
|
||||||
|
<target name="default" depends="clean,dist"/>
|
||||||
|
|
||||||
|
<target name="retrieve">
|
||||||
|
<ivy:retrieve pattern="${lib.dir}/[conf]/[artifact]-[revision].[ext]" conf="compile" pathid="compile.classpath"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="retrieve.test">
|
||||||
|
<ivy:retrieve pattern="${lib.dir}/[conf]/[artifact]-[revision].[ext]" conf="test" pathid="test.classpath"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="compile" depends="retrieve">
|
||||||
|
<mkdir dir="${bin.dir}"/>
|
||||||
|
<javac srcdir="${src.dir}" destdir="${bin.dir}" includeantruntime="false">
|
||||||
|
<classpath refid="compile.classpath"/>
|
||||||
|
</javac>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="compile.test" depends="compile,retrieve.test">
|
||||||
|
<mkdir dir="${test.bin.dir}"/>
|
||||||
|
<javac srcdir="${test.src.dir}" destdir="${test.bin.dir}" includeantruntime="false">
|
||||||
|
<classpath>
|
||||||
|
<path refid="test.classpath"/>
|
||||||
|
<pathelement location="${bin.dir}"/>
|
||||||
|
</classpath>
|
||||||
|
</javac>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="doc" depends="retrieve">
|
||||||
|
<javadoc sourcepath="${src.dir}" destdir="${doc.dir}" packagenames="com.muldersoft.slunkcrypt" public="true" overview="${src.dir}/overview.html" doctitle="SlunkCrypt" windowtitle="SlunkCrypt">
|
||||||
|
<classpath refid="compile.classpath"/>
|
||||||
|
</javadoc>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="dist" depends="compile,doc">
|
||||||
|
<mkdir dir="${out.dir}"/>
|
||||||
|
<jar jarfile="${out.dir}/slunkcrypt-1.jar" basedir="${bin.dir}"/>
|
||||||
|
<jar jarfile="${out.dir}/slunkcrypt-1-javadoc.jar" basedir="${doc.dir}"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="test" depends="compile.test">
|
||||||
|
<mkdir dir="${test.out.dir}"/>
|
||||||
|
<junitlauncher haltOnFailure="true" printSummary="true">
|
||||||
|
<classpath>
|
||||||
|
<path refid="test.classpath"/>
|
||||||
|
<pathelement location="${bin.dir}"/>
|
||||||
|
<pathelement location="${test.bin.dir}"/>
|
||||||
|
</classpath>
|
||||||
|
<testclasses outputdir="${test.out.dir}">
|
||||||
|
<fileset dir="${test.bin.dir}" includes="**/*Test.class"/>
|
||||||
|
</testclasses>
|
||||||
|
<listener type="legacy-xml"/>
|
||||||
|
</junitlauncher>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="clean">
|
||||||
|
<delete dir="${bin.dir}"/>
|
||||||
|
<delete dir="${doc.dir}"/>
|
||||||
|
<delete dir="${lib.dir}"/>
|
||||||
|
<delete dir="${out.dir}"/>
|
||||||
|
<delete dir="${test.bin.dir}"/>
|
||||||
|
<delete dir="${test.out.dir}"/>
|
||||||
|
</target>
|
||||||
|
</project>
|
14
binding/java/ivy.xml
Normal file
14
binding/java/ivy.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<ivy-module version="2.0">
|
||||||
|
<info organisation="com.muldersoft" module="slunkcrypt-jna"/>
|
||||||
|
<configurations>
|
||||||
|
<conf name="compile" visibility="public"/>
|
||||||
|
<conf name="test" visibility="private" extends="compile"/>
|
||||||
|
</configurations>
|
||||||
|
<dependencies>
|
||||||
|
<dependency org="net.java.dev.jna" name="jna" rev="5.14.0" conf="compile->default"/>
|
||||||
|
<dependency org="org.junit.jupiter" name="junit-jupiter-api" rev="5.10.3" conf="test->default"/>
|
||||||
|
<dependency org="org.junit.platform" name="junit-platform-engine" rev="1.10.3" conf="test->default"/>
|
||||||
|
<dependency org="org.junit.platform" name="junit-platform-launcher" rev="1.10.3" conf="test->default"/>
|
||||||
|
<dependency org="org.junit.jupiter" name="junit-jupiter-engine" rev="5.10.3" conf="test->default"/>
|
||||||
|
</dependencies>
|
||||||
|
</ivy-module>
|
@ -0,0 +1,158 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import com.muldersoft.slunkcrypt.SlunkCryptException.ErrorKind;
|
||||||
|
import com.muldersoft.slunkcrypt.internal.SlunkCryptLibrary;
|
||||||
|
import com.muldersoft.slunkcrypt.internal.SlunkCryptParam;
|
||||||
|
import com.muldersoft.slunkcrypt.internal.types.Context;
|
||||||
|
import com.muldersoft.slunkcrypt.internal.types.SizeT;
|
||||||
|
import com.muldersoft.slunkcrypt.internal.types.UInt64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The abstract base class for all {@link com.muldersoft.slunkcrypt.SlunkCrypt SlunkCrypt} implementations.
|
||||||
|
*/
|
||||||
|
abstract class AbstractSlunkCrypt implements SlunkCrypt {
|
||||||
|
|
||||||
|
private static final int PASSWD_LENGTH_MIN = 8;
|
||||||
|
private static final int PASSWD_LENGTH_MAX = 256;
|
||||||
|
|
||||||
|
private static final String PROPERTY_THREAD_COUNT = "slunkcrypt.thread_count";
|
||||||
|
|
||||||
|
private static final int SLUNKCRYPT_ENCRYPT = 0;
|
||||||
|
private static final int SLUNKCRYPT_DECRYPT = 1;
|
||||||
|
|
||||||
|
protected enum Mode {
|
||||||
|
Encrypt(SLUNKCRYPT_ENCRYPT),
|
||||||
|
Decrypt(SLUNKCRYPT_DECRYPT);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
private Mode(final int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int intValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
private final AtomicBoolean closed = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
protected AbstractSlunkCrypt(final String passwd, final long nonce, final Mode mode) throws SlunkCryptException {
|
||||||
|
this(Objects.requireNonNull(passwd, "passwd").getBytes(StandardCharsets.UTF_8), nonce, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractSlunkCrypt(final byte[] passwd, final long nonce, final Mode mode) throws SlunkCryptException {
|
||||||
|
if ((mode != Mode.Encrypt) && (mode != Mode.Decrypt)) {
|
||||||
|
throw new IllegalArgumentException("mode");
|
||||||
|
}
|
||||||
|
if ((passwd == null) || (passwd.length < PASSWD_LENGTH_MIN) || (passwd.length > PASSWD_LENGTH_MAX)) {
|
||||||
|
throw new IllegalArgumentException("passwd");
|
||||||
|
}
|
||||||
|
|
||||||
|
final SlunkCryptParam parameters = new SlunkCryptParam();
|
||||||
|
try {
|
||||||
|
final String threadCount = System.getProperty(PROPERTY_THREAD_COUNT);
|
||||||
|
if ((threadCount != null) && (!threadCount.isEmpty())) {
|
||||||
|
parameters.thread_count = SizeT.of(Long.parseUnsignedLong(threadCount));
|
||||||
|
}
|
||||||
|
} catch(final Exception e) {
|
||||||
|
throw new IllegalArgumentException(PROPERTY_THREAD_COUNT, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
context = SlunkCryptLibrary.INSTANCE.slunkcrypt_alloc_ext(UInt64.of(nonce), passwd, SizeT.of(passwd.length), mode.intValue(), parameters);
|
||||||
|
if (context.equals(Context.NULL)) {
|
||||||
|
throw new SlunkCryptException(ErrorKind.Failure, "Failed to create SlunkCrypt context!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final byte[] process(final byte[] input) throws SlunkCryptException {
|
||||||
|
if (input == null) {
|
||||||
|
throw new NullPointerException("input");
|
||||||
|
}
|
||||||
|
|
||||||
|
final byte[] output = new byte[input.length];
|
||||||
|
process(input, output);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void process(final byte[] input, final byte[] output) throws SlunkCryptException {
|
||||||
|
if (input == null) {
|
||||||
|
throw new NullPointerException("input");
|
||||||
|
}
|
||||||
|
if ((output == null) || (output.length < input.length)) {
|
||||||
|
throw new IllegalArgumentException("output");
|
||||||
|
}
|
||||||
|
|
||||||
|
checkState();
|
||||||
|
|
||||||
|
final int errorCode = SlunkCryptLibrary.INSTANCE.slunkcrypt_process(context, input, output, SizeT.of(input.length));
|
||||||
|
if (!SlunkCryptException.isSuccess(errorCode)) {
|
||||||
|
throw SlunkCryptException.mapErrorCode(errorCode, "Failed to process data!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void inplace(final byte[] buffer) throws SlunkCryptException {
|
||||||
|
if (buffer == null) {
|
||||||
|
throw new NullPointerException("input");
|
||||||
|
}
|
||||||
|
|
||||||
|
checkState();
|
||||||
|
|
||||||
|
final int errorCode = SlunkCryptLibrary.INSTANCE.slunkcrypt_inplace(context, buffer, SizeT.of(buffer.length));
|
||||||
|
if (!SlunkCryptException.isSuccess(errorCode)) {
|
||||||
|
throw SlunkCryptException.mapErrorCode(errorCode, "Failed to process data!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void reset(final String passwd, final long nonce, final Mode mode) throws SlunkCryptException {
|
||||||
|
reset(Objects.requireNonNull(passwd, "passwd").getBytes(StandardCharsets.UTF_8), nonce, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void reset(final byte[] passwd, final long nonce, final Mode mode) throws SlunkCryptException {
|
||||||
|
if ((mode != Mode.Encrypt) && (mode != Mode.Decrypt)) {
|
||||||
|
throw new IllegalArgumentException("mode");
|
||||||
|
}
|
||||||
|
if ((passwd == null) || (passwd.length < PASSWD_LENGTH_MIN) || (passwd.length > PASSWD_LENGTH_MAX)) {
|
||||||
|
throw new IllegalArgumentException("passwd");
|
||||||
|
}
|
||||||
|
|
||||||
|
checkState();
|
||||||
|
|
||||||
|
final int errorCode = SlunkCryptLibrary.INSTANCE.slunkcrypt_reset(context, UInt64.of(nonce), passwd, SizeT.of(passwd.length), mode.ordinal());
|
||||||
|
if (!SlunkCryptException.isSuccess(errorCode)) {
|
||||||
|
throw SlunkCryptException.mapErrorCode(errorCode, "Failed to process data!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
if (closed.compareAndSet(false, true)) {
|
||||||
|
SlunkCryptLibrary.INSTANCE.slunkcrypt_free(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return (!closed.get()) ? String.format("SlunkCrypt(0x%016X)", context.longValue()) : "SlunkCrypt(NULL)";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkState() {
|
||||||
|
if (closed.get()) {
|
||||||
|
throw new IllegalStateException("Instance is already closed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
138
binding/java/src/com/muldersoft/slunkcrypt/SlunkCrypt.java
Normal file
138
binding/java/src/com/muldersoft/slunkcrypt/SlunkCrypt.java
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.muldersoft.slunkcrypt.internal.SlunkCryptLibrary;
|
||||||
|
import com.muldersoft.slunkcrypt.internal.types.UInt64ByReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SlunkCrypt context for encryption or decryption.
|
||||||
|
* <p>Implementations of this interface wrap the “native” SlunkCrypt context and they provide the instance methods for {@link SlunkCrypt#process(byte[]) processing}, i.e. encrypting or decrypting, chunks of data.</p>
|
||||||
|
* <p>Separate implementations for {@link com.muldersoft.slunkcrypt.SlunkCryptEncryptor <i>encryption</i>} mode and {@link com.muldersoft.slunkcrypt.SlunkCryptDecryptor <i>decryption</i>} mode are available.</p>
|
||||||
|
* <p><b><i>Warning:</i></b> The wrapped “native” SlunkCrypt context must be released by calling the {@link SlunkCrypt#close close()} method, or otherwise a resource leak is imminent! Using <a href="https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html" target="_blank">try-with-resources</a> is recommended.</p>
|
||||||
|
* <h3>System properties:</h3>
|
||||||
|
* <table summary="System properties" border>
|
||||||
|
* <tr>
|
||||||
|
* <th><b>Property</b></th>
|
||||||
|
* <th><b>Meaning</b></th>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
|
* <td><tt>slunkcrypt.thread_count</tt></td>
|
||||||
|
* <td>The number of threads to be used internally by SlunkCrypt; a value of <b><tt>0</tt></b> means auto-detection (the default)</td>
|
||||||
|
* </tr>
|
||||||
|
* </table>
|
||||||
|
* <h2>Thread Safety</h2>
|
||||||
|
* <p>Separate <tt>SlunkCrypt</tt> instances can safely be accessed from concurrent threads <i>without</i> the need for any kind if synchronization, provided that each instance is only accessed by the single thread that has created the respective instance. In order to <i>share</i> the same <tt>SlunkCrypt</tt> instance between concurrent threads, every access to the “shared” instance must be synchronized explicitly by the callers!</p>
|
||||||
|
* <h2>Example</h2>
|
||||||
|
* <pre>{@code
|
||||||
|
* public class Main {
|
||||||
|
*
|
||||||
|
* private static String PASSPHRASE = "OrpheanBeholderScryDoubt";
|
||||||
|
*
|
||||||
|
* public static void main(String[] args) throws Exception {
|
||||||
|
* // Fill buffer with random data (plaintext)
|
||||||
|
* final byte[] buffer = new byte[64];
|
||||||
|
* ThreadLocalRandom.current().nextBytes(buffer);
|
||||||
|
*
|
||||||
|
* // Encrypt the data in-place
|
||||||
|
* final long nonce;
|
||||||
|
* try(final SlunkCryptEncryptor instance = new SlunkCryptEncryptor(PASSPHRASE)) {
|
||||||
|
* nonce = instance.getNonce();
|
||||||
|
* instance.inplace(buffer);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Decrypt the data in-place
|
||||||
|
* try(final SlunkCryptDecryptor instance = new SlunkCryptDecryptor(PASSPHRASE, nonce)) {
|
||||||
|
* instance.inplace(buffer);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }}</pre>
|
||||||
|
*/
|
||||||
|
public interface SlunkCrypt extends AutoCloseable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process, i.e. encrypt or decrypt, the next chunk of data.
|
||||||
|
* <p>This method is designed for stream processing. It is supposed to be called repeatedly, until all input data has been processed.</p>
|
||||||
|
* @param input the input buffer to be read; will <i>not</i> be modified
|
||||||
|
* @return the new buffer with the result
|
||||||
|
* @throws IllegalStateException the instance was already closed
|
||||||
|
* @throws SlunkCryptException the operation failed or it was aborted
|
||||||
|
* @throws IllegalArgumentException invalid parameters detected
|
||||||
|
* @throws IllegalStateException the instance has already been closed
|
||||||
|
*/
|
||||||
|
byte[] process(byte[] input) throws SlunkCryptException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process, i.e. encrypt or decrypt, the next chunk of data.
|
||||||
|
* <p>This method is designed for stream processing. It is supposed to be called repeatedly, until all input data has been processed.</p>
|
||||||
|
* <p><i>Note:</i> The size of the output buffer must be at least the size of the input buffer!</p>
|
||||||
|
* @param input the input buffer to be read; will <i>not</i> be modified
|
||||||
|
* @param output the output buffer to write the result to
|
||||||
|
* @throws IllegalStateException the instance was already closed
|
||||||
|
* @throws SlunkCryptException the operation failed or it was aborted
|
||||||
|
* @throws IllegalArgumentException invalid parameters detected
|
||||||
|
* @throws IllegalStateException the instance has already been closed
|
||||||
|
*/
|
||||||
|
void process(byte[] input, byte[] output) throws SlunkCryptException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process, i.e. encrypt or decrypt, the next chunk of data <i>in-place</i>.
|
||||||
|
* <p>This method is designed for stream processing. It is supposed to be called repeatedly, until all input data has been processed.</p>
|
||||||
|
* @param buffer the input/output buffer to be updated
|
||||||
|
* @throws IllegalStateException the instance was already closed
|
||||||
|
* @throws SlunkCryptException the operation failed or it was aborted
|
||||||
|
* @throws IllegalArgumentException invalid parameters detected
|
||||||
|
* @throws IllegalStateException the instance has already been closed
|
||||||
|
*/
|
||||||
|
void inplace(byte[] buffer) throws SlunkCryptException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a new random nonce.
|
||||||
|
* <p><i>Note:</i> The nonce is generating using a “strong” cryptographically secure pseudorandom number generator.</p>
|
||||||
|
* @return The new nonce value
|
||||||
|
* @throws SlunkCryptException the operation failed or it was aborted
|
||||||
|
*/
|
||||||
|
public static long generateNonce() throws SlunkCryptException {
|
||||||
|
final UInt64ByReference nonce = new UInt64ByReference();
|
||||||
|
final int errorCode = SlunkCryptLibrary.INSTANCE.slunkcrypt_generate_nonce(nonce);
|
||||||
|
if (!SlunkCryptException.isSuccess(errorCode)) {
|
||||||
|
throw SlunkCryptException.mapErrorCode(errorCode, "Failed to generate nonce!");
|
||||||
|
}
|
||||||
|
return nonce.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the version of the “native” SlunkCrypt library.
|
||||||
|
* @return The version number as <tt>Map<String, Short></tt>, containing the keys: <ul><li><tt>"slunkcrypt.version.major"</tt>,<li> <tt>"slunkcrypt.version.minor"</tt>, <li><tt>"slunkcrypt.version.patch"</tt></ul>
|
||||||
|
*/
|
||||||
|
public static Map<String, Short> getVersion() {
|
||||||
|
final Map<String, Short> version = new LinkedHashMap<String, Short>(3);
|
||||||
|
version.put(SlunkCryptLibrary.Version.MAJOR.getSymbolName().toLowerCase(Locale.US).replace('_', '.'), SlunkCryptLibrary.Version.MAJOR.getValue().shortValue());
|
||||||
|
version.put(SlunkCryptLibrary.Version.MINOR.getSymbolName().toLowerCase(Locale.US).replace('_', '.'), SlunkCryptLibrary.Version.MINOR.getValue().shortValue());
|
||||||
|
version.put(SlunkCryptLibrary.Version.PATCH.getSymbolName().toLowerCase(Locale.US).replace('_', '.'), SlunkCryptLibrary.Version.PATCH.getValue().shortValue());
|
||||||
|
return Collections.unmodifiableMap(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the build string of the “native” SlunkCrypt library.
|
||||||
|
* @return The build string, containing the build time and date, e.g. <tt>"Jun 24 2024, 21:55:08"</tt>
|
||||||
|
*/
|
||||||
|
public static String getBuild() {
|
||||||
|
return SlunkCryptLibrary.Version.BUILD.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the “native” SlunkCrypt context wrapped by this {@link com.muldersoft.slunkcrypt.SlunkCrypt SlunkCrypt} instance and release any system resources associated with it.
|
||||||
|
* <p><b><i>Warning:</i></b> Once this method has been called, this instance is left in an “invalidated” state and any attempt to process more data is going to throw an <tt>IllegalStateException</tt>!</p>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
void close();
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SlunkCrypt <i>decryption</i> context.
|
||||||
|
* <p>Wraps a “native” SlunkCrypt context that was initialized in <b><i>decryption</i></b> mode and implements the {@link com.muldersoft.slunkcrypt.SlunkCrypt SlunkCrypt} interface.</p>
|
||||||
|
*/
|
||||||
|
public class SlunkCryptDecryptor extends AbstractSlunkCrypt {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link com.muldersoft.slunkcrypt.SlunkCrypt SlunkCrypt} instance in <b><i>decryption</i></b> mode.
|
||||||
|
* @param passwd the password to be used for decryption (UTF-8)
|
||||||
|
* @param nonce the nonce to be used for decryption
|
||||||
|
* @throws SlunkCryptException the operation failed or it was aborted
|
||||||
|
* @throws IllegalArgumentException invalid parameters detected
|
||||||
|
*/
|
||||||
|
public SlunkCryptDecryptor(final String passwd, final long nonce) throws SlunkCryptException {
|
||||||
|
super(passwd, nonce, Mode.Decrypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link com.muldersoft.slunkcrypt.SlunkCrypt SlunkCrypt} instance in <b><i>decryption</i></b> mode.
|
||||||
|
* @param passwd the password to be used for decryption (binary)
|
||||||
|
* @param nonce the nonce to be used for decryption
|
||||||
|
* @throws SlunkCryptException the operation failed or it was aborted
|
||||||
|
* @throws IllegalArgumentException invalid parameters detected
|
||||||
|
*/
|
||||||
|
public SlunkCryptDecryptor(final byte[] passwd, final long nonce) throws SlunkCryptException {
|
||||||
|
super(passwd, nonce, Mode.Decrypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-initialize this {@link com.muldersoft.slunkcrypt.SlunkCryptEncryptor SlunkCryptDecryptor} instance.
|
||||||
|
* @param passwd the password to be used for decryption (UTF-8)
|
||||||
|
* @param nonce the nonce to be used for decryption
|
||||||
|
* @throws SlunkCryptException the operation failed or it was aborted
|
||||||
|
* @throws IllegalArgumentException invalid parameters detected
|
||||||
|
* @throws IllegalStateException the instance has already been closed
|
||||||
|
*/
|
||||||
|
public void reset(final String passwd, final long nonce) throws SlunkCryptException {
|
||||||
|
reset(passwd, nonce, Mode.Decrypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-initialize this {@link com.muldersoft.slunkcrypt.SlunkCryptEncryptor SlunkCryptDecryptor} instance.
|
||||||
|
* @param passwd the password to be used for decryption (binary)
|
||||||
|
* @param nonce the nonce to be used for decryption
|
||||||
|
* @throws SlunkCryptException the operation failed or it was aborted
|
||||||
|
* @throws IllegalArgumentException invalid parameters detected
|
||||||
|
* @throws IllegalStateException the instance has already been closed
|
||||||
|
*/
|
||||||
|
public void reset(final byte[] passwd, final long nonce) throws SlunkCryptException {
|
||||||
|
reset(passwd, nonce , Mode.Decrypt);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SlunkCrypt <i>encryption</i> context.
|
||||||
|
* <p>Wraps a “native” SlunkCrypt context that was initialized in <b><i>encryption</i></b> mode and implements the {@link com.muldersoft.slunkcrypt.SlunkCrypt SlunkCrypt} interface.</p>
|
||||||
|
*/
|
||||||
|
public class SlunkCryptEncryptor extends AbstractSlunkCrypt {
|
||||||
|
|
||||||
|
private long nonce;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link com.muldersoft.slunkcrypt.SlunkCrypt SlunkCrypt} instance in <b><i>encryption</i></b> mode.
|
||||||
|
* <p><i>Note:</i> This method implicitly generates a new random nonce. Use {@link SlunkCryptEncryptor#getNonce() getNonce()} to retrieve the nonce value.</p>
|
||||||
|
* @param passwd the password to be used for encryption (UTF-8)
|
||||||
|
* @throws SlunkCryptException the operation failed or it was aborted
|
||||||
|
* @throws IllegalArgumentException invalid parameters detected
|
||||||
|
*/
|
||||||
|
public SlunkCryptEncryptor(final String passwd) throws SlunkCryptException {
|
||||||
|
this(passwd, SlunkCrypt.generateNonce());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link com.muldersoft.slunkcrypt.SlunkCrypt SlunkCrypt} instance in <b><i>encryption</i></b> mode.
|
||||||
|
* <p><i>Note:</i> This method implicitly generates a new random nonce. Use {@link SlunkCryptEncryptor#getNonce() getNonce()} to retrieve the nonce value.</p>
|
||||||
|
* @param passwd the password to be used for encryption (binary)
|
||||||
|
* @throws SlunkCryptException the operation failed or it was aborted
|
||||||
|
* @throws IllegalArgumentException invalid parameters detected
|
||||||
|
*/
|
||||||
|
public SlunkCryptEncryptor(final byte[] passwd) throws SlunkCryptException {
|
||||||
|
this(passwd, SlunkCrypt.generateNonce());
|
||||||
|
}
|
||||||
|
|
||||||
|
private SlunkCryptEncryptor(final String passwd, final long nonce) throws SlunkCryptException {
|
||||||
|
super(passwd, nonce, Mode.Encrypt);
|
||||||
|
this.nonce = nonce;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SlunkCryptEncryptor(final byte[] passwd, final long nonce) throws SlunkCryptException {
|
||||||
|
super(passwd, nonce, Mode.Encrypt);
|
||||||
|
this.nonce = nonce;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-initialize this {@link com.muldersoft.slunkcrypt.SlunkCryptEncryptor SlunkCryptEncryptor} instance.
|
||||||
|
* <p><i>Note:</i> This method implicitly generates a new random nonce. Use {@link com.muldersoft.slunkcrypt.SlunkCryptEncryptor#getNonce() getNonce()} to retrieve the nonce value.</p>
|
||||||
|
* @param passwd the password to be used for encryption (UTF-8)
|
||||||
|
* @throws SlunkCryptException the operation failed or it was aborted
|
||||||
|
* @throws IllegalArgumentException invalid parameters detected
|
||||||
|
* @throws IllegalStateException the instance has already been closed
|
||||||
|
*/
|
||||||
|
public void reset(final String passwd) throws SlunkCryptException {
|
||||||
|
reset(passwd, nonce = SlunkCrypt.generateNonce(), Mode.Encrypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-initialize this {@link com.muldersoft.slunkcrypt.SlunkCryptEncryptor SlunkCryptEncryptor} instance.
|
||||||
|
* <p><i>Note:</i> This method implicitly generates a new random nonce. Use {@link com.muldersoft.slunkcrypt.SlunkCryptEncryptor#getNonce() getNonce()} to retrieve the nonce value.</p>
|
||||||
|
* @param passwd the password to be used for encryption (binary)
|
||||||
|
* @throws SlunkCryptException the operation failed or it was aborted
|
||||||
|
* @throws IllegalArgumentException invalid parameters detected
|
||||||
|
* @throws IllegalStateException the instance has already been closed
|
||||||
|
*/
|
||||||
|
public void reset(final byte[] passwd) throws SlunkCryptException {
|
||||||
|
reset(passwd, nonce = SlunkCrypt.generateNonce(), Mode.Encrypt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the nonce value that was generated for this {@link com.muldersoft.slunkcrypt.SlunkCryptEncryptor SlunkCryptEncryptor} instance.
|
||||||
|
* @return the nonce value
|
||||||
|
*/
|
||||||
|
public long getNonce() {
|
||||||
|
return nonce;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals that a SlunkCrypt operation has failed or that it has been aborted by the user.
|
||||||
|
* <p>Details are provided via {@link ErrorKind}.</p>
|
||||||
|
*/
|
||||||
|
public final class SlunkCryptException extends IOException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The kind of error that has triggered a {@link SlunkCryptException}.
|
||||||
|
*/
|
||||||
|
public enum ErrorKind {
|
||||||
|
/** The operation completed successfully. */
|
||||||
|
Success,
|
||||||
|
/** The operation has failed. */
|
||||||
|
Failure,
|
||||||
|
/** The operation was aborted by the user. */
|
||||||
|
Aborted,
|
||||||
|
/** An unknown kind of error has occurred. */
|
||||||
|
Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final ErrorKind kind;
|
||||||
|
|
||||||
|
private static final int SLUNKCRYPT_SUCCESS = 0;
|
||||||
|
private static final int SLUNKCRYPT_FAILURE = -1;
|
||||||
|
private static final int SLUNKCRYPT_ABORTED = -2;
|
||||||
|
|
||||||
|
SlunkCryptException(final ErrorKind kind, final String message) {
|
||||||
|
super(message);
|
||||||
|
this.kind = Objects.requireNonNull(kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isSuccess(final int errorCode) {
|
||||||
|
return errorCode == SLUNKCRYPT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SlunkCryptException mapErrorCode(final int errorCode, final String message) {
|
||||||
|
switch(errorCode) {
|
||||||
|
case SLUNKCRYPT_SUCCESS:
|
||||||
|
return new SlunkCryptException(ErrorKind.Success, message);
|
||||||
|
case SLUNKCRYPT_FAILURE:
|
||||||
|
return new SlunkCryptException(ErrorKind.Failure, message);
|
||||||
|
case SLUNKCRYPT_ABORTED:
|
||||||
|
return new SlunkCryptException(ErrorKind.Aborted, message);
|
||||||
|
default:
|
||||||
|
return new SlunkCryptException(ErrorKind.Unknown, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the kind of error that has triggered this exception.
|
||||||
|
* @return the {@link com.muldersoft.slunkcrypt.SlunkCryptException.ErrorKind ErrorKind}
|
||||||
|
*/
|
||||||
|
public ErrorKind getErrorKind() {
|
||||||
|
return kind;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt.internal;
|
||||||
|
|
||||||
|
import com.muldersoft.slunkcrypt.internal.types.Context;
|
||||||
|
import com.muldersoft.slunkcrypt.internal.types.SizeT;
|
||||||
|
import com.muldersoft.slunkcrypt.internal.types.UInt64;
|
||||||
|
import com.muldersoft.slunkcrypt.internal.types.UInt64ByReference;
|
||||||
|
import com.muldersoft.slunkcrypt.internal.utilities.Constant;
|
||||||
|
import com.muldersoft.slunkcrypt.internal.utilities.Constant.StrPtrConst;
|
||||||
|
import com.muldersoft.slunkcrypt.internal.utilities.Constant.UInt16Const;
|
||||||
|
import com.sun.jna.Library;
|
||||||
|
import com.sun.jna.Native;
|
||||||
|
|
||||||
|
public interface SlunkCryptLibrary extends Library {
|
||||||
|
|
||||||
|
static final SlunkCryptLibrary INSTANCE = Native.load("slunkcrypt-1", SlunkCryptLibrary.class);
|
||||||
|
|
||||||
|
static class Version {
|
||||||
|
public static final UInt16Const MAJOR = Constant.ofUInt16(INSTANCE, "SLUNKCRYPT_VERSION_MAJOR");
|
||||||
|
public static final UInt16Const MINOR = Constant.ofUInt16(INSTANCE, "SLUNKCRYPT_VERSION_MINOR");
|
||||||
|
public static final UInt16Const PATCH = Constant.ofUInt16(INSTANCE, "SLUNKCRYPT_VERSION_PATCH");
|
||||||
|
public static final StrPtrConst BUILD = Constant.ofStrPtr(INSTANCE, "SLUNKCRYPT_BUILD");
|
||||||
|
}
|
||||||
|
|
||||||
|
Context slunkcrypt_alloc_ext(UInt64 nonce, byte[] passwd, SizeT passwd_len, int mode, SlunkCryptParam param);
|
||||||
|
int slunkcrypt_reset(Context context, UInt64 nonce, byte[] passwd, SizeT passwd_len, int mode);
|
||||||
|
void slunkcrypt_free(Context context);
|
||||||
|
int slunkcrypt_inplace(Context context, byte[] buffer, SizeT data_len);
|
||||||
|
int slunkcrypt_process(Context context, byte[] input, byte[] output, SizeT data_len);
|
||||||
|
int slunkcrypt_generate_nonce(UInt64ByReference nonce);
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.muldersoft.slunkcrypt.internal;
|
||||||
|
|
||||||
|
import com.muldersoft.slunkcrypt.internal.types.SizeT;
|
||||||
|
import com.muldersoft.slunkcrypt.internal.types.UInt16;
|
||||||
|
import com.sun.jna.Structure;
|
||||||
|
import com.sun.jna.Structure.FieldOrder;
|
||||||
|
|
||||||
|
@FieldOrder({ "version", "thread_count", "legacy_compat", "debug_logging" })
|
||||||
|
public class SlunkCryptParam extends Structure {
|
||||||
|
|
||||||
|
public static final UInt16 SLUNK_PARAM_VERSION = UInt16.of((short)2);
|
||||||
|
|
||||||
|
public SlunkCryptParam() {
|
||||||
|
version = SLUNK_PARAM_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UInt16 version;
|
||||||
|
public SizeT thread_count;
|
||||||
|
public int legacy_compat;
|
||||||
|
public int debug_logging;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt.internal.types;
|
||||||
|
|
||||||
|
import com.sun.jna.IntegerType;
|
||||||
|
import com.sun.jna.Native;
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
|
||||||
|
public class Context extends IntegerType {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public static final Context NULL = new Context();
|
||||||
|
|
||||||
|
public Context() {
|
||||||
|
super(Native.POINTER_SIZE, Pointer.nativeValue(Pointer.NULL), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Context(final long value) {
|
||||||
|
super(Native.POINTER_SIZE, value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pointer toPointer() {
|
||||||
|
return Pointer.createConstant(longValue());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt.internal.types;
|
||||||
|
|
||||||
|
import com.sun.jna.IntegerType;
|
||||||
|
import com.sun.jna.Native;
|
||||||
|
|
||||||
|
public class SizeT extends IntegerType {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public SizeT() {
|
||||||
|
super(Native.SIZE_T_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SizeT(final long value) {
|
||||||
|
super(Native.SIZE_T_SIZE, value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SizeT of(final long value) {
|
||||||
|
return new SizeT(value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt.internal.types;
|
||||||
|
|
||||||
|
import com.sun.jna.IntegerType;
|
||||||
|
|
||||||
|
public class UInt16 extends IntegerType {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public UInt16() {
|
||||||
|
super(Short.BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UInt16(final long value) {
|
||||||
|
super(Short.BYTES, value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UInt16 of(final long value) {
|
||||||
|
return new UInt16(value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt.internal.types;
|
||||||
|
|
||||||
|
import com.sun.jna.IntegerType;
|
||||||
|
|
||||||
|
public class UInt64 extends IntegerType {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public UInt64() {
|
||||||
|
super(Long.BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UInt64(final long value) {
|
||||||
|
super(Long.BYTES, value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UInt64 of(final long value) {
|
||||||
|
return new UInt64(value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt.internal.types;
|
||||||
|
|
||||||
|
import com.sun.jna.ptr.ByReference;
|
||||||
|
|
||||||
|
public class UInt64ByReference extends ByReference {
|
||||||
|
|
||||||
|
public UInt64ByReference() {
|
||||||
|
super(Long.BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UInt64ByReference(final long value) {
|
||||||
|
super(Long.BYTES);
|
||||||
|
setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(final long value) {
|
||||||
|
getPointer().setLong(0, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getValue() {
|
||||||
|
return getPointer().getLong(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UInt64ByReference of(final long value) {
|
||||||
|
return new UInt64ByReference(value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt.internal.utilities;
|
||||||
|
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
import com.muldersoft.slunkcrypt.internal.types.UInt16;
|
||||||
|
import com.sun.jna.Library;
|
||||||
|
import com.sun.jna.Library.Handler;
|
||||||
|
import com.sun.jna.NativeLibrary;
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
|
||||||
|
public class Constant {
|
||||||
|
|
||||||
|
private static final String UTF_8 = StandardCharsets.UTF_8.name();
|
||||||
|
|
||||||
|
private static final Map<Library, NativeLibrary> NATIVE_LIBRARY = Collections.synchronizedMap(new WeakHashMap<Library, NativeLibrary>());
|
||||||
|
|
||||||
|
protected final Pointer address;
|
||||||
|
|
||||||
|
protected final String symbolName;
|
||||||
|
|
||||||
|
protected Constant(final NativeLibrary nativeLibrary, final String symbolName) {
|
||||||
|
this.symbolName = Objects.requireNonNull(symbolName);
|
||||||
|
address = nativeLibrary.getGlobalVariableAddress(symbolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static NativeLibrary getNativeLibrary(final Library library) {
|
||||||
|
return NATIVE_LIBRARY.computeIfAbsent(library, key -> ((Handler)Proxy.getInvocationHandler(key)).getNativeLibrary());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UInt16Const ofUInt16(final Library library, final String symbolName) {
|
||||||
|
return new UInt16Const(getNativeLibrary(library), symbolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StrPtrConst ofStrPtr(final Library library, final String symbolName) {
|
||||||
|
return new StrPtrConst(getNativeLibrary(library), symbolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class UInt16Const extends Constant {
|
||||||
|
|
||||||
|
protected UInt16Const(final NativeLibrary nativeLibrary, final String symbolName) {
|
||||||
|
super(nativeLibrary, symbolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UInt16 getValue() {
|
||||||
|
return UInt16.of(address.getShort(0L));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StrPtrConst extends Constant {
|
||||||
|
|
||||||
|
protected StrPtrConst(final NativeLibrary nativeLibrary, final String symbolName) {
|
||||||
|
super(nativeLibrary, symbolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return address.getPointer(0L).getString(0L, UTF_8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSymbolName() {
|
||||||
|
return symbolName;
|
||||||
|
}
|
||||||
|
}
|
27
binding/java/src/overview.html
Normal file
27
binding/java/src/overview.html
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>SlunkCrypt Java Wrapper</h1>
|
||||||
|
<p>This package exposes the functionality of the <a href="https://gitlab.com/lord_mulder/slunkcrypt" target="_blank"><b>SlunkCrypt</b></a> library to to Java developers.</p>
|
||||||
|
<p>Please see the {@see com.muldersoft.slunkcrypt.SlunkCrypt} class for details!</p>
|
||||||
|
<h2>Dependencies</h2>
|
||||||
|
The SlunkCrypt Java wrapper requires <a href="https://mvnrepository.com/artifact/net.java.dev.jna/jna" target="_blank">Java Native Access (JNA)</a>, version 5.14.x or later, as a runtime dependency.
|
||||||
|
<h2>Build Instructions</h2>
|
||||||
|
<p>First the "native" SlunkCrypt library needs to be built, if not done yet:</p>
|
||||||
|
<pre>$ cd /home/JohnnyBeSlunk/dev/SlunkCrypt
|
||||||
|
$ make -B SHARED=1</pre>
|
||||||
|
<p>Now build the SlunkCrypt Java wrapper package:</p>
|
||||||
|
<pre>$ cd binding/java
|
||||||
|
$ ant</pre>
|
||||||
|
<h3>Prerequisites</h3>
|
||||||
|
<p><a href="https://ant.apache.org/bindownload.cgi">Apache Ant</a> and <a href="https://ant.apache.org/ivy/download.cgi" target="_blank">Apache Ivy</a> are required for buildig the SlunkCrypt Java wrapper from the sources using the provided <tt>build.xml</tt> file.</p>
|
||||||
|
<p><i>Note:</i> The file <tt>ivy.jar</tt> should be located in the <tt>ANT_HOME/lib</tt> directory.</p>
|
||||||
|
<p>
|
||||||
|
<h2>Unit Tests</h2>
|
||||||
|
In order to run the unit tests, please type:
|
||||||
|
<pre>$ export ANT_OPTS=-Djna.library.path=$PWD/../../libslunkcrypt/lib
|
||||||
|
$ ant test</pre>
|
||||||
|
<h3>Prerequisites</h3>
|
||||||
|
<p>The <a href="https://mvnrepository.com/artifact/org.apache.ant/ant-junitlauncher">JUnitLauncher</a> (JUnit 5) is required to run the unit tests. All other required JUnit 5 libraries will be fetched automatically by Ivy.</p>
|
||||||
|
<p><i>Note:</i> The file <tt>ant-junitlauncher.jar</tt> should be located in the <tt>ANT_HOME/lib</tt> directory.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,248 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt.tests;
|
||||||
|
|
||||||
|
import static com.muldersoft.slunkcrypt.tests.Utilities.toHexString;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
|
||||||
|
import org.junit.jupiter.api.Order;
|
||||||
|
import org.junit.jupiter.api.RepeatedTest;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.TestInfo;
|
||||||
|
import org.junit.jupiter.api.TestInstance;
|
||||||
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
|
|
||||||
|
import com.muldersoft.slunkcrypt.SlunkCryptDecryptor;
|
||||||
|
import com.muldersoft.slunkcrypt.SlunkCryptEncryptor;
|
||||||
|
|
||||||
|
@TestMethodOrder(OrderAnnotation.class)
|
||||||
|
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||||
|
public class ContextTest {
|
||||||
|
|
||||||
|
private static final String PASSPHRASE = "OrpheanBeholderScryDoubt";
|
||||||
|
|
||||||
|
private String lastTestName = new String();
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void init(final TestInfo testInfo) {
|
||||||
|
final String name = testInfo.getTestMethod().map(method -> method.getName()).orElse("N/A");
|
||||||
|
if (!name.equalsIgnoreCase(lastTestName)) {
|
||||||
|
System.out.printf("-------- [ %s ] --------%n", lastTestName = name);
|
||||||
|
} else {
|
||||||
|
System.out.println("----");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RepeatedTest(8)
|
||||||
|
@Order(1)
|
||||||
|
void createInstanceTest() throws Exception {
|
||||||
|
try(final SlunkCryptEncryptor encryptor = new SlunkCryptEncryptor(PASSPHRASE)) {
|
||||||
|
assertNotNull(encryptor);
|
||||||
|
System.out.printf("EncryptContext: %s%n", encryptor);
|
||||||
|
try(final SlunkCryptDecryptor decryptor = new SlunkCryptDecryptor(PASSPHRASE, encryptor.getNonce())) {
|
||||||
|
assertNotNull(decryptor);
|
||||||
|
System.out.printf("DecryptContext: %s%n", decryptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RepeatedTest(8)
|
||||||
|
@Order(2)
|
||||||
|
void processTest() throws Exception {
|
||||||
|
final long nonce;
|
||||||
|
final byte[] plaintext = new byte[256], encrypted = new byte[256], decrypted = new byte[256];
|
||||||
|
ThreadLocalRandom.current().nextBytes(plaintext);
|
||||||
|
|
||||||
|
System.out.printf("Plaintext: %s%n", toHexString(plaintext));
|
||||||
|
|
||||||
|
try(final SlunkCryptEncryptor instance = new SlunkCryptEncryptor(PASSPHRASE)) {
|
||||||
|
nonce = instance.getNonce();
|
||||||
|
instance.process(plaintext, encrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Encrypted: %s%n", toHexString(encrypted));
|
||||||
|
assertFalse(Arrays.equals(encrypted, plaintext));
|
||||||
|
|
||||||
|
try(final SlunkCryptDecryptor instance = new SlunkCryptDecryptor(PASSPHRASE, nonce)) {
|
||||||
|
instance.process(encrypted, decrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Decrypted: %s%n", toHexString(decrypted));
|
||||||
|
assertTrue(Arrays.equals(decrypted, plaintext));
|
||||||
|
}
|
||||||
|
|
||||||
|
@RepeatedTest(8)
|
||||||
|
@Order(3)
|
||||||
|
void processTest2() throws Exception {
|
||||||
|
final long nonce;
|
||||||
|
final byte[] plaintext = new byte[256], encrypted, decrypted;
|
||||||
|
ThreadLocalRandom.current().nextBytes(plaintext);
|
||||||
|
|
||||||
|
System.out.printf("Plaintext: %s%n", toHexString(plaintext));
|
||||||
|
|
||||||
|
try(final SlunkCryptEncryptor instance = new SlunkCryptEncryptor(PASSPHRASE)) {
|
||||||
|
nonce = instance.getNonce();
|
||||||
|
encrypted = instance.process(plaintext);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Encrypted: %s%n", toHexString(encrypted));
|
||||||
|
assertFalse(Arrays.equals(encrypted, plaintext));
|
||||||
|
|
||||||
|
try(final SlunkCryptDecryptor instance = new SlunkCryptDecryptor(PASSPHRASE, nonce)) {
|
||||||
|
decrypted = instance.process(encrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Decrypted: %s%n", toHexString(decrypted));
|
||||||
|
assertTrue(Arrays.equals(decrypted, plaintext));
|
||||||
|
}
|
||||||
|
|
||||||
|
@RepeatedTest(8)
|
||||||
|
@Order(4)
|
||||||
|
void inplaceTest() throws Exception {
|
||||||
|
final long nonce;
|
||||||
|
final byte[] plaintext = new byte[256], encrypted = new byte[256], decrypted = new byte[256];
|
||||||
|
ThreadLocalRandom.current().nextBytes(plaintext);
|
||||||
|
|
||||||
|
System.out.printf("Plaintext: %s%n", toHexString(plaintext));
|
||||||
|
|
||||||
|
try(final SlunkCryptEncryptor instance = new SlunkCryptEncryptor(PASSPHRASE)) {
|
||||||
|
nonce = instance.getNonce();
|
||||||
|
System.arraycopy(plaintext, 0, encrypted, 0, plaintext.length);
|
||||||
|
instance.inplace(encrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Encrypted: %s%n", toHexString(encrypted));
|
||||||
|
assertFalse(Arrays.equals(encrypted, plaintext));
|
||||||
|
|
||||||
|
try(final SlunkCryptDecryptor instance = new SlunkCryptDecryptor(PASSPHRASE, nonce)) {
|
||||||
|
System.arraycopy(encrypted, 0, decrypted, 0, encrypted.length);
|
||||||
|
instance.inplace(decrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Decrypted: %s%n", toHexString(decrypted));
|
||||||
|
assertTrue(Arrays.equals(decrypted, plaintext));
|
||||||
|
}
|
||||||
|
|
||||||
|
@RepeatedTest(8)
|
||||||
|
@Order(5)
|
||||||
|
void resetTest() throws Exception {
|
||||||
|
final long nonce_1, nonce_2;
|
||||||
|
final byte[] plaintext = new byte[256], encrypted_1 = new byte[256], encrypted_2 = new byte[256], decrypted_1 = new byte[256], decrypted_2 = new byte[256];
|
||||||
|
ThreadLocalRandom.current().nextBytes(plaintext);
|
||||||
|
|
||||||
|
System.out.printf("Plaintext: %s%n", toHexString(plaintext));
|
||||||
|
|
||||||
|
try(final SlunkCryptEncryptor instance = new SlunkCryptEncryptor(PASSPHRASE)) {
|
||||||
|
nonce_1 = instance.getNonce();
|
||||||
|
System.arraycopy(plaintext, 0, encrypted_1, 0, plaintext.length);
|
||||||
|
instance.inplace(encrypted_1);
|
||||||
|
instance.reset(PASSPHRASE);
|
||||||
|
nonce_2 = instance.getNonce();
|
||||||
|
System.arraycopy(plaintext, 0, encrypted_2, 0, plaintext.length);
|
||||||
|
instance.inplace(encrypted_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Encrypted: %s%n", toHexString(encrypted_1));
|
||||||
|
assertFalse(Arrays.equals(encrypted_1, plaintext));
|
||||||
|
System.out.printf("Encrypted: %s%n", toHexString(encrypted_2));
|
||||||
|
assertFalse(Arrays.equals(encrypted_2, plaintext));
|
||||||
|
|
||||||
|
try(final SlunkCryptDecryptor instance = new SlunkCryptDecryptor(PASSPHRASE, nonce_1)) {
|
||||||
|
System.arraycopy(encrypted_1, 0, decrypted_1, 0, encrypted_1.length);
|
||||||
|
instance.inplace(decrypted_1);
|
||||||
|
instance.reset(PASSPHRASE, nonce_2);
|
||||||
|
System.arraycopy(encrypted_2, 0, decrypted_2, 0, encrypted_2.length);
|
||||||
|
instance.inplace(decrypted_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Decrypted: %s%n", toHexString(decrypted_1));
|
||||||
|
assertTrue(Arrays.equals(decrypted_1, plaintext));
|
||||||
|
System.out.printf("Decrypted: %s%n", toHexString(decrypted_2));
|
||||||
|
assertTrue(Arrays.equals(decrypted_2, plaintext));
|
||||||
|
}
|
||||||
|
|
||||||
|
@RepeatedTest(8)
|
||||||
|
@Order(6)
|
||||||
|
void failBadNonceTest() throws Exception {
|
||||||
|
final long nonce;
|
||||||
|
final byte[] plaintext = new byte[256], encrypted = new byte[256], decrypted = new byte[256];
|
||||||
|
ThreadLocalRandom.current().nextBytes(plaintext);
|
||||||
|
|
||||||
|
System.out.printf("Plaintext: %s%n", toHexString(plaintext));
|
||||||
|
|
||||||
|
try(final SlunkCryptEncryptor instance = new SlunkCryptEncryptor(PASSPHRASE)) {
|
||||||
|
nonce = instance.getNonce();
|
||||||
|
System.arraycopy(plaintext, 0, encrypted, 0, plaintext.length);
|
||||||
|
instance.inplace(encrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Encrypted: %s%n", toHexString(encrypted));
|
||||||
|
assertFalse(Arrays.equals(encrypted, plaintext));
|
||||||
|
|
||||||
|
try(final SlunkCryptDecryptor instance = new SlunkCryptDecryptor(PASSPHRASE, nonce + 1)) {
|
||||||
|
System.arraycopy(encrypted, 0, decrypted, 0, encrypted.length);
|
||||||
|
instance.inplace(decrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Decrypted: %s%n", toHexString(decrypted));
|
||||||
|
assertFalse(Arrays.equals(decrypted, plaintext));
|
||||||
|
}
|
||||||
|
|
||||||
|
@RepeatedTest(8)
|
||||||
|
@Order(7)
|
||||||
|
void failBadPasswdTest() throws Exception {
|
||||||
|
final long nonce;
|
||||||
|
final byte[] plaintext = new byte[256], encrypted = new byte[256], decrypted = new byte[256];
|
||||||
|
ThreadLocalRandom.current().nextBytes(plaintext);
|
||||||
|
System.out.printf("Plaintext: %s%n", toHexString(plaintext));
|
||||||
|
|
||||||
|
try(final SlunkCryptEncryptor instance = new SlunkCryptEncryptor(PASSPHRASE)) {
|
||||||
|
nonce = instance.getNonce();
|
||||||
|
System.arraycopy(plaintext, 0, encrypted, 0, plaintext.length);
|
||||||
|
instance.inplace(encrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Encrypted: %s%n", toHexString(encrypted));
|
||||||
|
assertFalse(Arrays.equals(encrypted, plaintext));
|
||||||
|
|
||||||
|
try(final SlunkCryptDecryptor instance = new SlunkCryptDecryptor(PASSPHRASE.replace('O', '0'), nonce)) {
|
||||||
|
System.arraycopy(encrypted, 0, decrypted, 0, encrypted.length);
|
||||||
|
instance.inplace(decrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Decrypted: %s%n", toHexString(decrypted));
|
||||||
|
assertFalse(Arrays.equals(decrypted, plaintext));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(8)
|
||||||
|
void stressTest() throws Exception {
|
||||||
|
try(final SlunkCryptEncryptor encryptor = new SlunkCryptEncryptor(PASSPHRASE)) {
|
||||||
|
try(final SlunkCryptDecryptor decryptor = new SlunkCryptDecryptor(PASSPHRASE, encryptor.getNonce())) {
|
||||||
|
final byte[] plaintext = new byte[0xFFFF], processed = new byte[0xFFFF];
|
||||||
|
for (int i = 0; i < 0xFFFF; ++i) {
|
||||||
|
ThreadLocalRandom.current().nextBytes(plaintext);
|
||||||
|
System.arraycopy(plaintext, 0, processed, 0, plaintext.length);
|
||||||
|
encryptor.inplace(processed);
|
||||||
|
assertFalse(Arrays.equals(processed, plaintext));
|
||||||
|
decryptor.inplace(processed);
|
||||||
|
assertTrue(Arrays.equals(processed, plaintext));
|
||||||
|
if (i % 499 == 0) {
|
||||||
|
System.out.printf("%.1f%%%n", (i / (double)0xFFFF) * 100.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.printf("%5.1f%%%n", 100.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
package com.muldersoft.slunkcrypt.tests;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
|
||||||
|
import org.junit.jupiter.api.Order;
|
||||||
|
import org.junit.jupiter.api.RepeatedTest;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.TestInfo;
|
||||||
|
import org.junit.jupiter.api.TestInstance;
|
||||||
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
|
|
||||||
|
import com.muldersoft.slunkcrypt.SlunkCrypt;
|
||||||
|
import com.muldersoft.slunkcrypt.SlunkCryptException;
|
||||||
|
|
||||||
|
@TestMethodOrder(OrderAnnotation.class)
|
||||||
|
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||||
|
public class FunctionTest {
|
||||||
|
|
||||||
|
private String lastTestName = new String();
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void init(final TestInfo testInfo) {
|
||||||
|
final String name = testInfo.getTestMethod().map(method -> method.getName()).orElse("N/A");
|
||||||
|
if (!name.equalsIgnoreCase(lastTestName)) {
|
||||||
|
System.out.printf("-------- [ %s ] --------%n", lastTestName = name);
|
||||||
|
} else {
|
||||||
|
System.out.println("----");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(1)
|
||||||
|
void getVersionTest() {
|
||||||
|
final Map<String, Short> versionInfo = SlunkCrypt.getVersion();
|
||||||
|
assertNotNull(versionInfo);
|
||||||
|
final Short major, minor, patch;
|
||||||
|
assertNotNull(major = versionInfo.get("slunkcrypt.version.major"));
|
||||||
|
assertNotNull(minor = versionInfo.get("slunkcrypt.version.minor"));
|
||||||
|
assertNotNull(patch = versionInfo.get("slunkcrypt.version.patch"));
|
||||||
|
System.out.printf("Version: %d.%d.%d%n", major.shortValue(), minor.shortValue(), patch.shortValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(2)
|
||||||
|
void getBuildTest() {
|
||||||
|
final String build = SlunkCrypt.getBuild();
|
||||||
|
assertNotNull(build);
|
||||||
|
assertFalse(build.isEmpty());
|
||||||
|
System.out.printf("Build: \"%s\"%n", build);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RepeatedTest(8)
|
||||||
|
@Order(3)
|
||||||
|
void generateNonceTest() throws SlunkCryptException {
|
||||||
|
final long nonce_1 = SlunkCrypt.generateNonce();
|
||||||
|
System.out.printf("Nonce: %016X%n", nonce_1);
|
||||||
|
|
||||||
|
final long nonce_2 = SlunkCrypt.generateNonce();
|
||||||
|
System.out.printf("Nonce: %016X%n", nonce_2);
|
||||||
|
|
||||||
|
assertNotEquals(nonce_1, nonce_2);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.muldersoft.slunkcrypt.tests;
|
||||||
|
|
||||||
|
public class Utilities {
|
||||||
|
|
||||||
|
private Utilities() {
|
||||||
|
throw new IllegalAccessError();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toHexString(final byte[] data) {
|
||||||
|
final StringBuilder sb = new StringBuilder(Math.multiplyExact(2, data.length));
|
||||||
|
for (final byte b : data) {
|
||||||
|
sb.append(String.format("%02X", b));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
101
binding/rust/Cargo.lock
generated
Normal file
101
binding/rust/Cargo.lock
generated
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.2.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.155"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memx"
|
||||||
|
version = "0.1.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93022fcc0eab2dc9dd134e362592e06f0b3c0aa549ae91d8b3e539e56c2a0687"
|
||||||
|
dependencies = [
|
||||||
|
"cpufeatures",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slunkcrypt-rs"
|
||||||
|
version = "1.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"hex",
|
||||||
|
"memx",
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
9
binding/rust/Cargo.toml
Normal file
9
binding/rust/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "slunkcrypt-rs"
|
||||||
|
version = "1.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
hex = "0.4.3"
|
||||||
|
memx = "0.1.32"
|
||||||
|
rand = "0.8.5"
|
11
binding/rust/build.rs
Normal file
11
binding/rust/build.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!(r"cargo:rustc-link-search={}/../../libslunkcrypt/lib", env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||||
|
println!(r"cargo:rustc-link-lib=slunkcrypt-1");
|
||||||
|
}
|
31
binding/rust/examples/slunkcrypt_example.rs
Normal file
31
binding/rust/examples/slunkcrypt_example.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
use slunkcrypt_rs::{SlunkCrypt, SlunkCryptPasswd};
|
||||||
|
use hex;
|
||||||
|
use rand::{thread_rng, RngCore};
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Create passphrase from string
|
||||||
|
const PASSPHRASE: SlunkCryptPasswd = SlunkCryptPasswd::Str("OrpheanBeholderScryDoubt");
|
||||||
|
|
||||||
|
// Fill buffer with random data (plaintext)
|
||||||
|
let mut buffer = [ 0u8; 64 ];
|
||||||
|
thread_rng().fill_bytes(&mut buffer);
|
||||||
|
println!("Plaintext: {}", hex::encode(&buffer));
|
||||||
|
|
||||||
|
// Encrypt the data in-place
|
||||||
|
let (mut context_enc, nonce) = SlunkCrypt::init_encrypt(&PASSPHRASE, None).expect("Failed to create encryption context!");
|
||||||
|
context_enc.inplace(&mut buffer).expect("Failed to encrypt data!");
|
||||||
|
mem::drop(context_enc);
|
||||||
|
println!("Encrypted: {}", hex::encode(&buffer));
|
||||||
|
|
||||||
|
// Decrypt the data in-place
|
||||||
|
let mut context_dec = SlunkCrypt::init_decrypt(&PASSPHRASE, nonce, None).expect("Failed to create decryption context!");
|
||||||
|
context_dec.inplace(&mut buffer).expect("Failed to decrypt data!");
|
||||||
|
mem::drop(context_dec);
|
||||||
|
println!("Decrypted: {}", hex::encode(&buffer));
|
||||||
|
}
|
185
binding/rust/src/context.rs
Normal file
185
binding/rust/src/context.rs
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
use std::num::NonZeroUsize;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
use crate::error::{SlunkCryptError, SlunkCryptErrorKind};
|
||||||
|
use crate::functions::generate_nonce;
|
||||||
|
use crate::ffi::libslunkcrypt::{self, slunkcrypt_t, slunkparam_t, SLUNKCRYPT_SUCCESS, SLUNKCRYPT_NULL};
|
||||||
|
use crate::passwd::SlunkCryptPasswd;
|
||||||
|
|
||||||
|
/// SlunkCrypt context for encryption or decryption.
|
||||||
|
///
|
||||||
|
/// This struct wraps the "native" SlunkCrypt context. It provides functions for allocating a new encryption or decryption context as well as functions for processing, i.e. encrypting or decrypting, the next chunk of data within a specific `SlunkCrypt` context.
|
||||||
|
///
|
||||||
|
/// The wrapped "native" SlunkCrypt context is freed automatically when this struct is dropped.
|
||||||
|
///
|
||||||
|
/// # Thread safety
|
||||||
|
///
|
||||||
|
/// Separate `SlunkCrypt` contexts can safely be accessed from concurrent threads *without* the need for any kind if synchronization, provided that each context is only accessed by the *single* thread that has allocated the respective context.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// use slunkcrypt_rs::{SlunkCrypt, SlunkCryptPasswd};
|
||||||
|
/// use hex;
|
||||||
|
/// use rand::{thread_rng, RngCore};
|
||||||
|
/// use std::mem;
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// // Create passphrase from string
|
||||||
|
/// const PASSPHRASE: SlunkCryptPasswd = SlunkCryptPasswd::Str("OrpheanBeholderScryDoubt");
|
||||||
|
///
|
||||||
|
/// // Fill buffer with random data (plaintext)
|
||||||
|
/// let mut buffer = [ 0u8; 64 ];
|
||||||
|
/// thread_rng().fill_bytes(&mut buffer);
|
||||||
|
/// println!("Plaintext: {}", hex::encode(&buffer));
|
||||||
|
///
|
||||||
|
/// // Encrypt the data in-place
|
||||||
|
/// let (mut context_enc, nonce) = SlunkCrypt::init_encrypt(&PASSPHRASE, None).unwrap();
|
||||||
|
/// context_enc.inplace(&mut buffer).unwrap();
|
||||||
|
/// mem::drop(context_enc);
|
||||||
|
/// println!("Encrypted: {}", hex::encode(&buffer));
|
||||||
|
///
|
||||||
|
/// // Decrypt the data in-place
|
||||||
|
/// let mut context_dec = SlunkCrypt::init_decrypt(&PASSPHRASE, nonce, None).unwrap();
|
||||||
|
/// context_dec.inplace(&mut buffer).unwrap();
|
||||||
|
/// mem::drop(context_dec);
|
||||||
|
/// println!("Decrypted: {}", hex::encode(&buffer));
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SlunkCrypt {
|
||||||
|
context: slunkcrypt_t
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SlunkCrypt {
|
||||||
|
/// Create a new SlunkCrypt context and initialize it for the specified mode with the given password and the given nonce.
|
||||||
|
///
|
||||||
|
/// If successful, returns the new context; otherwise returns an [error code](SlunkCryptError).
|
||||||
|
fn new(passwd: &SlunkCryptPasswd, nonce: u64, mode: i32, threads: Option<NonZeroUsize>) -> Result<Self, SlunkCryptError> {
|
||||||
|
if passwd.len() < libslunkcrypt::SLUNKCRYPT_PWDLEN_MIN {
|
||||||
|
return Err(SlunkCryptError::new(SlunkCryptErrorKind::Invalid, "Passphrase is too short!"));
|
||||||
|
}
|
||||||
|
if passwd.len() > libslunkcrypt::SLUNKCRYPT_PWDLEN_MAX {
|
||||||
|
return Err(SlunkCryptError::new(SlunkCryptErrorKind::Invalid, "Passphrase is too long!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let param = slunkparam_t {
|
||||||
|
version: libslunkcrypt::SLUNKCRYPT_PARAM_VERSION,
|
||||||
|
thread_count: threads.map_or(usize::default(), NonZeroUsize::get),
|
||||||
|
legacy_compat: i32::default(),
|
||||||
|
debug_logging: i32::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let context: slunkcrypt_t = unsafe {
|
||||||
|
libslunkcrypt::slunkcrypt_alloc_ext(nonce, passwd.as_bytes().as_ptr() as *const u8, passwd.len(), mode, ¶m)
|
||||||
|
};
|
||||||
|
|
||||||
|
if context == SLUNKCRYPT_NULL {
|
||||||
|
Err(SlunkCryptError::new(SlunkCryptErrorKind::Failure, "failed to allocate slunkcrypt encryption context!"))
|
||||||
|
} else {
|
||||||
|
Ok(Self { context })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new SlunkCrypt context and initialize it for *encryption* mode with the given password and a fresh random nonce.
|
||||||
|
///
|
||||||
|
/// If successful, returns the new context and the generated nonce; otherwise returns an [error code](SlunkCryptError).
|
||||||
|
pub fn init_encrypt(passwd: &SlunkCryptPasswd, threads: Option<NonZeroUsize>) -> Result<(Self, u64), SlunkCryptError> {
|
||||||
|
let nonce = generate_nonce()?;
|
||||||
|
match Self::new(passwd, nonce, libslunkcrypt::SLUNKCRYPT_ENCRYPT, threads) {
|
||||||
|
Ok(context) => Ok((context, nonce)),
|
||||||
|
Err(error) => Err(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new SlunkCrypt context and initialize it for *decryption* mode with the given password and the given nonce.
|
||||||
|
///
|
||||||
|
/// If successful, returns the new context; otherwise returns an [error code](SlunkCryptError).
|
||||||
|
pub fn init_decrypt(passwd: &SlunkCryptPasswd, nonce: u64, threads: Option<NonZeroUsize>) -> Result<Self, SlunkCryptError> {
|
||||||
|
Self::new(passwd, nonce, libslunkcrypt::SLUNKCRYPT_DECRYPT, threads)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_encrypt(&mut self, passwd: &SlunkCryptPasswd) -> Result<u64, SlunkCryptError> {
|
||||||
|
if passwd.len() < libslunkcrypt::SLUNKCRYPT_PWDLEN_MIN {
|
||||||
|
return Err(SlunkCryptError::new(SlunkCryptErrorKind::Invalid, "Passphrase is too short!"));
|
||||||
|
}
|
||||||
|
if passwd.len() > libslunkcrypt::SLUNKCRYPT_PWDLEN_MAX {
|
||||||
|
return Err(SlunkCryptError::new(SlunkCryptErrorKind::Invalid, "Passphrase is too long!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let nonce = generate_nonce()?;
|
||||||
|
|
||||||
|
let retval = unsafe {
|
||||||
|
libslunkcrypt::slunkcrypt_reset(self.context, nonce, passwd.as_bytes().as_ptr(), passwd.len(), libslunkcrypt::SLUNKCRYPT_ENCRYPT)
|
||||||
|
};
|
||||||
|
match retval {
|
||||||
|
SLUNKCRYPT_SUCCESS => Ok(nonce),
|
||||||
|
_ => Err(SlunkCryptError::from_retval(retval, "failed to reset encryption context!"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_decrypt(&mut self, passwd: &SlunkCryptPasswd, nonce: u64) -> Result<(), SlunkCryptError> {
|
||||||
|
if passwd.len() < libslunkcrypt::SLUNKCRYPT_PWDLEN_MIN {
|
||||||
|
return Err(SlunkCryptError::new(SlunkCryptErrorKind::Invalid, "Passphrase is too short!"));
|
||||||
|
}
|
||||||
|
if passwd.len() > libslunkcrypt::SLUNKCRYPT_PWDLEN_MAX {
|
||||||
|
return Err(SlunkCryptError::new(SlunkCryptErrorKind::Invalid, "Passphrase is too long!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let retval = unsafe {
|
||||||
|
libslunkcrypt::slunkcrypt_reset(self.context, nonce, passwd.as_bytes().as_ptr(), passwd.len(), libslunkcrypt::SLUNKCRYPT_DECRYPT)
|
||||||
|
};
|
||||||
|
match retval {
|
||||||
|
SLUNKCRYPT_SUCCESS => Ok(()),
|
||||||
|
_ => Err(SlunkCryptError::from_retval(retval, "failed to reset decryption context!"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process the next chunk of data. The given input data is encrypted or decrypted into the output buffer.
|
||||||
|
///
|
||||||
|
/// Does **not** modify the data in the input buffer.
|
||||||
|
///
|
||||||
|
/// If successful, returns nothing; otherwise returns an [error code](SlunkCryptError).
|
||||||
|
pub fn process(&mut self, data_in: &[u8], data_out: &mut[u8]) -> Result<(), SlunkCryptError> {
|
||||||
|
if data_out.len() < data_in.len() {
|
||||||
|
return Err(SlunkCryptError::new(SlunkCryptErrorKind::Invalid, "The output buffer is too small!"));
|
||||||
|
}
|
||||||
|
let retval = unsafe {
|
||||||
|
libslunkcrypt::slunkcrypt_process(self.context, data_in.as_ptr(), data_out.as_mut_ptr(), data_in.len())
|
||||||
|
};
|
||||||
|
match retval {
|
||||||
|
SLUNKCRYPT_SUCCESS => Ok(()),
|
||||||
|
_ => Err(SlunkCryptError::from_retval(retval, "failed to process data!"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process the next chunk of data. The given data is encrypted or decrypted *in-place*.
|
||||||
|
///
|
||||||
|
/// If successful, returns nothing; otherwise returns an [error code](SlunkCryptError).
|
||||||
|
pub fn inplace(&mut self, data: &mut[u8]) -> Result<(), SlunkCryptError> {
|
||||||
|
let retval = unsafe {
|
||||||
|
libslunkcrypt::slunkcrypt_inplace(self.context, data.as_mut_ptr(), data.len())
|
||||||
|
};
|
||||||
|
match retval {
|
||||||
|
SLUNKCRYPT_SUCCESS => Ok(()),
|
||||||
|
_ => Err(SlunkCryptError::from_retval(retval, "failed to process data!"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for SlunkCrypt {
|
||||||
|
/// Free the SlunkCrypt context and release all of its associated ressources.
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.context != SLUNKCRYPT_NULL {
|
||||||
|
unsafe {
|
||||||
|
libslunkcrypt::slunkcrypt_free(self.context);
|
||||||
|
}
|
||||||
|
let x : *const std::ffi::c_void = ptr::null();
|
||||||
|
self.context = x as slunkcrypt_t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
binding/rust/src/error.rs
Normal file
61
binding/rust/src/error.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
use std::os::raw::c_int;
|
||||||
|
use crate::ffi::libslunkcrypt::{SLUNKCRYPT_ABORTED, SLUNKCRYPT_FAILURE, SLUNKCRYPT_SUCCESS};
|
||||||
|
|
||||||
|
/// SlunkCrypt error type.
|
||||||
|
///
|
||||||
|
/// This struct provides information about the SlunkCrypt error that has occurred.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SlunkCryptError {
|
||||||
|
kind: SlunkCryptErrorKind,
|
||||||
|
description: &'static str
|
||||||
|
}
|
||||||
|
|
||||||
|
/// SlunkCrypt error kind enumeration.
|
||||||
|
///
|
||||||
|
/// This enumeration defines the *kind* of the SlunkCrypt error that has occurred.
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum SlunkCryptErrorKind {
|
||||||
|
/// The operation succeeded.
|
||||||
|
Success,
|
||||||
|
/// The operation was **not** executed because of invalid arguments.
|
||||||
|
Invalid,
|
||||||
|
/// The operation has failed.
|
||||||
|
Failure,
|
||||||
|
/// The operation was aborted by the user.
|
||||||
|
Aborted,
|
||||||
|
/// Unknown error. This is **not** supposed to happen.
|
||||||
|
Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SlunkCryptError {
|
||||||
|
/// Creates a new error from the given kind and description.
|
||||||
|
pub(crate) fn new(kind: SlunkCryptErrorKind, description: &'static str) -> Self {
|
||||||
|
Self { kind, description }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new error from the given error code and description.
|
||||||
|
pub(crate) fn from_retval(retval: c_int, description: &'static str) -> Self {
|
||||||
|
let kind = match retval {
|
||||||
|
SLUNKCRYPT_SUCCESS => SlunkCryptErrorKind::Success,
|
||||||
|
SLUNKCRYPT_ABORTED => SlunkCryptErrorKind::Aborted,
|
||||||
|
SLUNKCRYPT_FAILURE => SlunkCryptErrorKind::Failure,
|
||||||
|
_ => SlunkCryptErrorKind::Unknown
|
||||||
|
};
|
||||||
|
Self::new(kind, description)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the [*kind*](SlunkCryptErrorKind) of the SlunkCrypt error that has occurred.
|
||||||
|
pub fn kind(&self) -> SlunkCryptErrorKind {
|
||||||
|
self.kind
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a detailed textual description of the SlunkCrypt error that has occurred.
|
||||||
|
pub fn description(&self) -> &'static str {
|
||||||
|
&self.description
|
||||||
|
}
|
||||||
|
}
|
50
binding/rust/src/ffi/libslunkcrypt.rs
Normal file
50
binding/rust/src/ffi/libslunkcrypt.rs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
pub type slunkcrypt_t = usize;
|
||||||
|
|
||||||
|
const NULL_POINTER: *const ::std::ffi::c_void = ::std::ptr::null();
|
||||||
|
pub const SLUNKCRYPT_NULL: slunkcrypt_t = unsafe { ::std::mem::transmute(NULL_POINTER) };
|
||||||
|
|
||||||
|
pub const SLUNKCRYPT_FALSE: ::std::os::raw::c_int = 0;
|
||||||
|
pub const SLUNKCRYPT_TRUE: ::std::os::raw::c_int = 1;
|
||||||
|
pub const SLUNKCRYPT_ENCRYPT: ::std::os::raw::c_int = 0;
|
||||||
|
pub const SLUNKCRYPT_DECRYPT: ::std::os::raw::c_int = 1;
|
||||||
|
pub const SLUNKCRYPT_SUCCESS: ::std::os::raw::c_int = 0;
|
||||||
|
pub const SLUNKCRYPT_FAILURE: ::std::os::raw::c_int = -1;
|
||||||
|
pub const SLUNKCRYPT_ABORTED: ::std::os::raw::c_int = -2;
|
||||||
|
|
||||||
|
pub const SLUNKCRYPT_PWDLEN_MIN: usize = 8;
|
||||||
|
pub const SLUNKCRYPT_PWDLEN_MAX: usize = 256;
|
||||||
|
|
||||||
|
pub const SLUNKCRYPT_PARAM_VERSION: u16 = 2;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct slunkparam_t {
|
||||||
|
pub version: u16,
|
||||||
|
pub thread_count: usize,
|
||||||
|
pub legacy_compat: ::std::os::raw::c_int,
|
||||||
|
pub debug_logging: ::std::os::raw::c_int,
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
pub static SLUNKCRYPT_VERSION_MAJOR: u16;
|
||||||
|
pub static SLUNKCRYPT_VERSION_MINOR: u16;
|
||||||
|
pub static SLUNKCRYPT_VERSION_PATCH: u16;
|
||||||
|
pub static SLUNKCRYPT_BUILD: *const ::std::os::raw::c_char;
|
||||||
|
pub static SLUNKCRYPT_HAVE_THREADS: ::std::os::raw::c_int;
|
||||||
|
pub static mut g_slunkcrypt_abort_flag: ::std::os::raw::c_int;
|
||||||
|
|
||||||
|
pub fn slunkcrypt_generate_nonce(nonce: *mut u64) -> ::std::os::raw::c_int;
|
||||||
|
pub fn slunkcrypt_alloc_ext(nonce: u64, passwd: *const u8, passwd_len: usize, mode: ::std::os::raw::c_int, param: *const slunkparam_t) -> slunkcrypt_t;
|
||||||
|
pub fn slunkcrypt_reset(context: slunkcrypt_t, nonce: u64, passwd: *const u8, passwd_len: usize, mode: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
|
||||||
|
pub fn slunkcrypt_free(context: slunkcrypt_t);
|
||||||
|
pub fn slunkcrypt_process(context: slunkcrypt_t, input: *const u8, output: *mut u8, length: usize) -> ::std::os::raw::c_int;
|
||||||
|
pub fn slunkcrypt_inplace(context: slunkcrypt_t, buffer: *mut u8, length: usize) -> ::std::os::raw::c_int;
|
||||||
|
pub fn slunkcrypt_random_bytes(buffer: *mut u8, length: usize) -> usize;
|
||||||
|
pub fn slunkcrypt_bzero(buffer: *mut ::std::os::raw::c_void, length: usize);
|
||||||
|
|
||||||
|
}
|
13
binding/rust/src/ffi/mod.rs
Normal file
13
binding/rust/src/ffi/mod.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![allow(unused)]
|
||||||
|
#![allow(non_upper_case_globals)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
pub mod libslunkcrypt;
|
38
binding/rust/src/functions.rs
Normal file
38
binding/rust/src/functions.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
use std::ffi::CStr;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
use crate::error::SlunkCryptError;
|
||||||
|
use crate::ffi::libslunkcrypt::{self, SLUNKCRYPT_SUCCESS};
|
||||||
|
|
||||||
|
/// Generate a fresh random nonce, using a Cryptographically secure pseudorandom number generator.
|
||||||
|
pub fn generate_nonce() -> Result<u64, SlunkCryptError> {
|
||||||
|
let mut nonce: u64 = u64::default();
|
||||||
|
let retval = unsafe {
|
||||||
|
libslunkcrypt::slunkcrypt_generate_nonce(&mut nonce)
|
||||||
|
};
|
||||||
|
match retval {
|
||||||
|
SLUNKCRYPT_SUCCESS => Ok(nonce),
|
||||||
|
_ => Err(SlunkCryptError::from_retval(retval, "failed to generate nonce!"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the version of the native SlunkCrypt library.
|
||||||
|
pub fn get_version() -> (u16,u16,u16) {
|
||||||
|
unsafe {(
|
||||||
|
libslunkcrypt::SLUNKCRYPT_VERSION_MAJOR,
|
||||||
|
libslunkcrypt::SLUNKCRYPT_VERSION_MINOR,
|
||||||
|
libslunkcrypt::SLUNKCRYPT_VERSION_PATCH
|
||||||
|
)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the version of the native SlunkCrypt library.
|
||||||
|
pub fn get_build() -> &'static str {
|
||||||
|
unsafe {
|
||||||
|
CStr::from_ptr(libslunkcrypt::SLUNKCRYPT_BUILD).to_str().unwrap()
|
||||||
|
}
|
||||||
|
}
|
43
binding/rust/src/lib.rs
Normal file
43
binding/rust/src/lib.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
//! # SlunkCrypt Rust Wrapper
|
||||||
|
//! This crate exposes the functionality of the [**SlunkCrypt**](https://gitlab.com/lord_mulder/slunkcrypt) library to to Rust developers.
|
||||||
|
//!
|
||||||
|
//! Please see the [`SlunkCrypt`] struct for details!
|
||||||
|
//!
|
||||||
|
//! ## Build Instructions
|
||||||
|
//!
|
||||||
|
//! First the "native" SlunkCrypt library needs to be built, if not done yet:
|
||||||
|
//! ```sh
|
||||||
|
//! $ cd /home/JohnnyBeSlunk/dev/SlunkCrypt
|
||||||
|
//! $ make -B SHARED=1
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! Now build the SlunkCrypt Rust wrapper crate:
|
||||||
|
//! ```sh
|
||||||
|
//! $ cd binding/rust
|
||||||
|
//! $ cargo build --release
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! ## Unit Tests
|
||||||
|
//!
|
||||||
|
//! In order to run the unit tests, please type:
|
||||||
|
//!
|
||||||
|
//! ```sh
|
||||||
|
//! $ export LD_LIBRARY_PATH=/home/JohnnyBeSlunk/dev/SlunkCryptlibslunkcrypt/lib
|
||||||
|
//! $cargo test --release
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
mod context;
|
||||||
|
mod error;
|
||||||
|
mod ffi;
|
||||||
|
mod functions;
|
||||||
|
mod passwd;
|
||||||
|
|
||||||
|
pub use context::SlunkCrypt;
|
||||||
|
pub use error::{SlunkCryptError, SlunkCryptErrorKind};
|
||||||
|
pub use functions::{generate_nonce, get_version, get_build};
|
||||||
|
pub use passwd::SlunkCryptPasswd;
|
36
binding/rust/src/passwd.rs
Normal file
36
binding/rust/src/passwd.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/// Passphrase to be used with [SlunkCrypt](crate::SlunkCrypt) encryption or decryption.
|
||||||
|
pub enum SlunkCryptPasswd<'a> {
|
||||||
|
/// A passphrase constructed from a `&str`
|
||||||
|
Str(&'a str),
|
||||||
|
/// A passphrase constructed from a `String`
|
||||||
|
String(String),
|
||||||
|
/// A passphrase constructed from `&[u8]`
|
||||||
|
Bytes(&'a[u8]),
|
||||||
|
/// A passphrase constructed from `Vec<u8>`
|
||||||
|
Vec(Vec<u8>)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> SlunkCryptPasswd<'a> {
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
Self::Str(str) => str.len(),
|
||||||
|
Self::String(str) => str.len(),
|
||||||
|
Self::Bytes(bin) => bin.len(),
|
||||||
|
Self::Vec(bin) => bin.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_bytes(&'a self) -> &'a[u8] {
|
||||||
|
match self {
|
||||||
|
Self::Str(str) => str.as_bytes(),
|
||||||
|
Self::String(str) => str.as_bytes(),
|
||||||
|
Self::Bytes(bin) => bin,
|
||||||
|
Self::Vec(bin) => bin.as_slice()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
188
binding/rust/tests/context_test.rs
Normal file
188
binding/rust/tests/context_test.rs
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
use slunkcrypt_rs::{SlunkCryptPasswd, SlunkCrypt};
|
||||||
|
use hex;
|
||||||
|
use memx;
|
||||||
|
use rand::{rngs::OsRng, RngCore};
|
||||||
|
use std::{env, mem, cmp::Ordering};
|
||||||
|
|
||||||
|
const DEFAULT_TEST_LOOPS: usize = 8;
|
||||||
|
const PASSPHRASE: SlunkCryptPasswd = SlunkCryptPasswd::Str("eUGAwxOm0QwiVnDx");
|
||||||
|
const PASSPHRASE_BAD: SlunkCryptPasswd = SlunkCryptPasswd::Str("eUGAwxOm1QwiVnDx");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_instance() {
|
||||||
|
run_test(|| {
|
||||||
|
let (context, nonce) = SlunkCrypt::init_encrypt(&PASSPHRASE, None).expect("Failed to create encryption context!");
|
||||||
|
println!("EncryptContext: {:?}", context);
|
||||||
|
let context = SlunkCrypt::init_decrypt(&PASSPHRASE, nonce, None).expect("Failed to create decryption context!");
|
||||||
|
println!("DecryptContext: {:?}", context);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_process() {
|
||||||
|
run_test(|| {
|
||||||
|
let (mut orig, mut encr, mut decr) = ([ 0u8; 5003 ], [ 0u8; 5003 ], [ 0u8; 5003 ]);
|
||||||
|
OsRng.fill_bytes(&mut orig);
|
||||||
|
println!("Plaintext: {}", hex::encode(&orig));
|
||||||
|
|
||||||
|
let (mut context_enc, nonce) = SlunkCrypt::init_encrypt(&PASSPHRASE, None).expect("Failed to create encryption context!");
|
||||||
|
context_enc.process(&orig, &mut encr).expect("Failed to encrypt data!");
|
||||||
|
mem::drop(context_enc);
|
||||||
|
|
||||||
|
println!("Encrypted: {}", hex::encode(&encr));
|
||||||
|
assert!(memx::memcmp(&orig, &encr) != Ordering::Equal);
|
||||||
|
|
||||||
|
let mut context_dec = SlunkCrypt::init_decrypt(&PASSPHRASE, nonce, None).expect("Failed to create decryption context!");
|
||||||
|
context_dec.process(&encr, &mut decr).expect("Failed to encrypt data!");
|
||||||
|
mem::drop(context_dec);
|
||||||
|
|
||||||
|
println!("Decrypted: {}", hex::encode(&decr));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_inplace() {
|
||||||
|
run_test(|| {
|
||||||
|
let (mut data, mut orig) = ([ 0u8; 5003 ], [ 0u8; 5003 ]);
|
||||||
|
OsRng.fill_bytes(&mut data);
|
||||||
|
memx::memcpy(&mut orig, &data).expect("Failed to copy original data!");
|
||||||
|
|
||||||
|
println!("Plaintext: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) == Ordering::Equal);
|
||||||
|
|
||||||
|
let (mut context_enc, nonce) = SlunkCrypt::init_encrypt(&PASSPHRASE, None).expect("Failed to create encryption context!");
|
||||||
|
context_enc.inplace(&mut data).expect("Failed to encrypt data!");
|
||||||
|
mem::drop(context_enc);
|
||||||
|
|
||||||
|
println!("Encrypted: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) != Ordering::Equal);
|
||||||
|
|
||||||
|
let mut context_dec = SlunkCrypt::init_decrypt(&PASSPHRASE, nonce, None).expect("Failed to create decryption context!");
|
||||||
|
context_dec.inplace(&mut data).expect("Failed to decrypt data!");
|
||||||
|
mem::drop(context_dec);
|
||||||
|
|
||||||
|
println!("Decrypted: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) == Ordering::Equal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_reset() {
|
||||||
|
run_test(|| {
|
||||||
|
let (mut data, mut orig) = ([ 0u8; 5003 ], [ 0u8; 5003 ]);
|
||||||
|
OsRng.fill_bytes(&mut data);
|
||||||
|
memx::memcpy(&mut orig, &data).expect("Failed to copy original data!");
|
||||||
|
|
||||||
|
println!("Plaintext: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) == Ordering::Equal);
|
||||||
|
|
||||||
|
let (mut context, _nonce) = SlunkCrypt::init_encrypt(&PASSPHRASE, None).expect("Failed to create encryption context!");
|
||||||
|
context.inplace(&mut data).expect("Failed to encrypt data!");
|
||||||
|
|
||||||
|
println!("Encrypted: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) != Ordering::Equal);
|
||||||
|
|
||||||
|
memx::memcpy(&mut data, &orig).expect("Failed to copy original data!");
|
||||||
|
println!("Plaintext: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) == Ordering::Equal);
|
||||||
|
|
||||||
|
let nonce = context.reset_encrypt(&PASSPHRASE).expect("Failed to reset encryption context!");
|
||||||
|
context.inplace(&mut data).expect("Failed to encrypt data!");
|
||||||
|
|
||||||
|
println!("Encrypted: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) != Ordering::Equal);
|
||||||
|
|
||||||
|
context.reset_decrypt(&PASSPHRASE, nonce).expect("Failed to reset decryption context!");
|
||||||
|
context.inplace(&mut data).expect("Failed to decrypt data!");
|
||||||
|
mem::drop(context);
|
||||||
|
|
||||||
|
println!("Decrypted: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) == Ordering::Equal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fail_bad_nonce() {
|
||||||
|
run_test(|| {
|
||||||
|
let (mut data, mut orig) = ([ 0u8; 5003 ], [ 0u8; 5003 ]);
|
||||||
|
OsRng.fill_bytes(&mut data);
|
||||||
|
memx::memcpy(&mut orig, &data).expect("Failed to copy original data!");
|
||||||
|
|
||||||
|
println!("Plaintext: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) == Ordering::Equal);
|
||||||
|
|
||||||
|
let (mut context_enc, nonce) = SlunkCrypt::init_encrypt(&PASSPHRASE, None).expect("Failed to create encryption context!");
|
||||||
|
context_enc.inplace(&mut data).expect("Failed to encrypt data!");
|
||||||
|
mem::drop(context_enc);
|
||||||
|
|
||||||
|
println!("Encrypted: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) != Ordering::Equal);
|
||||||
|
|
||||||
|
let mut context_dec = SlunkCrypt::init_decrypt(&PASSPHRASE, nonce + 1, None).expect("Failed to create decryption context!");
|
||||||
|
context_dec.inplace(&mut data).expect("Failed to decrypt data!");
|
||||||
|
mem::drop(context_dec);
|
||||||
|
|
||||||
|
println!("Decrypted: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) != Ordering::Equal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fail_bad_passwd() {
|
||||||
|
run_test(|| {
|
||||||
|
let (mut data, mut orig) = ([ 0u8; 5003 ], [ 0u8; 5003 ]);
|
||||||
|
OsRng.fill_bytes(&mut data);
|
||||||
|
memx::memcpy(&mut orig, &data).expect("Failed to copy original data!");
|
||||||
|
|
||||||
|
println!("Plaintext: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) == Ordering::Equal);
|
||||||
|
|
||||||
|
let (mut context_enc, nonce) = SlunkCrypt::init_encrypt(&PASSPHRASE, None).expect("Failed to create encryption context!");
|
||||||
|
context_enc.inplace(&mut data).expect("Failed to encrypt data!");
|
||||||
|
mem::drop(context_enc);
|
||||||
|
|
||||||
|
println!("Encrypted: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) != Ordering::Equal);
|
||||||
|
|
||||||
|
let mut context_dec = SlunkCrypt::init_decrypt(&PASSPHRASE_BAD, nonce, None).expect("Failed to create decryption context!");
|
||||||
|
context_dec.inplace(&mut data).expect("Failed to decrypt data!");
|
||||||
|
mem::drop(context_dec);
|
||||||
|
|
||||||
|
println!("Decrypted: {}", hex::encode(&data));
|
||||||
|
assert!(memx::memcmp(&data, &orig) != Ordering::Equal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stress() {
|
||||||
|
let (mut data, mut orig) = ([ 0u8; u16::MAX as usize ], [ 0u8; u16::MAX as usize ]);
|
||||||
|
|
||||||
|
let (mut context_enc, nonce) = SlunkCrypt::init_encrypt(&PASSPHRASE, None).expect("Failed to create encryption context!");
|
||||||
|
let mut context_dec = SlunkCrypt::init_decrypt(&PASSPHRASE, nonce, None).expect("Failed to create decryption context!");
|
||||||
|
for i in 0..u16::MAX {
|
||||||
|
OsRng.fill_bytes(&mut data);
|
||||||
|
memx::memcpy(&mut orig, &data).expect("Failed to copy original data!");
|
||||||
|
|
||||||
|
context_enc.inplace(&mut data).expect("Failed to encrypt data!");
|
||||||
|
assert!(memx::memcmp(&data, &orig) != Ordering::Equal);
|
||||||
|
|
||||||
|
context_dec.inplace(&mut data).expect("Failed to decrypt data!");
|
||||||
|
assert!(memx::memcmp(&data, &orig) == Ordering::Equal);
|
||||||
|
|
||||||
|
if i % 499 == 0 {
|
||||||
|
println!("{:.1}%", (i as f64 / u16::MAX as f64) * 100.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_test<F>(func: F) where F: Fn() {
|
||||||
|
let loops = env::var("TEST_LOOPS").map_or(DEFAULT_TEST_LOOPS, |value| value.parse::<usize>().unwrap());
|
||||||
|
for _ in 0..loops {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
37
binding/rust/tests/functions_test.rs
Normal file
37
binding/rust/tests/functions_test.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use slunkcrypt_rs::{get_version, get_build, generate_nonce};
|
||||||
|
|
||||||
|
const DEFAULT_TEST_LOOPS: usize = 8;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_version() {
|
||||||
|
let (major, minor, patch) = get_version();
|
||||||
|
assert!(major > 0);
|
||||||
|
println!("Version: {}.{}.{}", major, minor, patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_build() {
|
||||||
|
let build = get_build();
|
||||||
|
println!("Build: \"{}\"", build);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_init_generate_nonce() {
|
||||||
|
run_test(|| {
|
||||||
|
let nonce = generate_nonce().expect("Failed to generate nonce!");
|
||||||
|
println!("Nonce: {:16X}", nonce);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_test<F>(func: F) where F: Fn() {
|
||||||
|
let loops = env::var("TEST_LOOPS").map_or(DEFAULT_TEST_LOOPS, |value| value.parse::<usize>().unwrap());
|
||||||
|
for _ in 0..loops {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,17 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
if [ -n "$1" ]; then CC="$1"; elif [ -z "$CC" ]; then CC="cc"; fi
|
if [ -n "$1" ]; then CC="$1"; elif [ -z "$CC" ]; then CC="cc"; fi
|
||||||
|
|
||||||
|
if [ -e /etc/os-release ]; then
|
||||||
|
PLATFORM_NAME="`cat /etc/os-release | egrep '^PRETTY_NAME=' | cut -c 13- | tr -d '\042'`"
|
||||||
|
elif [ -x /usr/bin/sw_vers ]; then
|
||||||
|
PLATFORM_NAME="`/usr/bin/sw_vers -productName` `/usr/bin/sw_vers -productVersion`"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$PLATFORM_NAME" ]; then
|
||||||
|
PLATFORM_NAME="`uname -s -r -v -m`"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Built : `date -u +'%Y-%m-%d %H:%M:%S'`"
|
echo "Built : `date -u +'%Y-%m-%d %H:%M:%S'`"
|
||||||
echo "Platform : `uname -s -r -v -m`"
|
echo "Platform : $PLATFORM_NAME"
|
||||||
echo "Target : `$CC -dumpmachine`"
|
echo "Target : `$CC -dumpmachine`"
|
||||||
echo "Compiler : `$CC -v 2>&1 | egrep -i '(gcc|clang)[[:space:]]+version' 2>/dev/null | head -n 1`"
|
echo "Compiler : `$CC -v 2>&1 | egrep -i '(gcc|clang)[[:space:]]+version' 2>/dev/null | head -n 1`"
|
||||||
|
@ -3,7 +3,7 @@ set -e
|
|||||||
cd -- "$(dirname -- "${0}")/../../.."
|
cd -- "$(dirname -- "${0}")/../../.."
|
||||||
|
|
||||||
if [ -z "${cc_path}" ]; then
|
if [ -z "${cc_path}" ]; then
|
||||||
cc_path="/usr/local/bin/gcc13"
|
cc_path="/usr/local/bin/gcc14"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mk_slunk() {
|
mk_slunk() {
|
||||||
@ -18,8 +18,6 @@ fi
|
|||||||
|
|
||||||
rm -rf "out" && mkdir -p "out"
|
rm -rf "out" && mkdir -p "out"
|
||||||
|
|
||||||
gmake CC="${cc_path}" clean
|
|
||||||
|
|
||||||
mk_slunk 32 "i686" "pentiumpro" "pentium3"
|
mk_slunk 32 "i686" "pentiumpro" "pentium3"
|
||||||
mk_slunk 64 "x86_64" "x86-64" "nocona"
|
mk_slunk 64 "x86_64" "x86-64" "nocona"
|
||||||
|
|
||||||
|
@ -15,9 +15,11 @@ fi
|
|||||||
|
|
||||||
rm -rf "out" && mkdir -p "out"
|
rm -rf "out" && mkdir -p "out"
|
||||||
|
|
||||||
$BASH -x -c "make clean"
|
if [ "$(arch)" == "x86_64" ]; then
|
||||||
|
mk_slunk "x86_64" "x86_64-gnu" "MARCH=x86-64 MTUNE=nocona"
|
||||||
|
else
|
||||||
mk_slunk "i686" "i686-gnu" "MARCH=pentiumpro MTUNE=pentium3"
|
mk_slunk "i686" "i686-gnu" "MARCH=pentiumpro MTUNE=pentium3"
|
||||||
|
fi
|
||||||
|
|
||||||
./etc/build/build_info.sh "gcc" > "out/.build_info"
|
./etc/build/build_info.sh "gcc" > "out/.build_info"
|
||||||
|
|
||||||
|
@ -14,8 +14,6 @@ fi
|
|||||||
|
|
||||||
rm -rf "out" && mkdir -p "out"
|
rm -rf "out" && mkdir -p "out"
|
||||||
|
|
||||||
make clean
|
|
||||||
|
|
||||||
case "${BE_HOST_CPU}" in
|
case "${BE_HOST_CPU}" in
|
||||||
x86_64)
|
x86_64)
|
||||||
mk_slunk "gcc" "x86_64" "x86-64" "nocona"
|
mk_slunk "gcc" "x86_64" "x86-64" "nocona"
|
||||||
|
@ -19,8 +19,6 @@ fi
|
|||||||
|
|
||||||
rm -rf "out" && mkdir -p "out"
|
rm -rf "out" && mkdir -p "out"
|
||||||
|
|
||||||
$BASH -x -c "make clean"
|
|
||||||
|
|
||||||
mk_slunk "x86_64" "x86_64-linux-gnu" "MARCH=x86-64 MTUNE=nocona"
|
mk_slunk "x86_64" "x86_64-linux-gnu" "MARCH=x86-64 MTUNE=nocona"
|
||||||
mk_slunk "i686" "i686-linux-gnu" "MARCH=pentiumpro MTUNE=pentium3"
|
mk_slunk "i686" "i686-linux-gnu" "MARCH=pentiumpro MTUNE=pentium3"
|
||||||
|
|
||||||
|
@ -20,8 +20,6 @@ fi
|
|||||||
|
|
||||||
rm -rf "out" && mkdir -p "out"
|
rm -rf "out" && mkdir -p "out"
|
||||||
|
|
||||||
$BASH -x -c "make clean"
|
|
||||||
|
|
||||||
mk_slunk "x86_64" "MARCH=x86-64 MTUNE=nocona"
|
mk_slunk "x86_64" "MARCH=x86-64 MTUNE=nocona"
|
||||||
mk_slunk "i686" "MARCH=pentiumpro MTUNE=pentium3"
|
mk_slunk "i686" "MARCH=pentiumpro MTUNE=pentium3"
|
||||||
|
|
||||||
|
@ -13,8 +13,6 @@ mk_slunk() {
|
|||||||
|
|
||||||
rm -rf "out" && mkdir -p "out"
|
rm -rf "out" && mkdir -p "out"
|
||||||
|
|
||||||
make CC="${cc_path}" clean
|
|
||||||
|
|
||||||
mk_slunk "x86_64"
|
mk_slunk "x86_64"
|
||||||
mk_slunk "arm64"
|
mk_slunk "arm64"
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ set -e
|
|||||||
cd -- "$(dirname -- "${0}")/../../.."
|
cd -- "$(dirname -- "${0}")/../../.."
|
||||||
|
|
||||||
if [ -z "${cc_path}" ]; then
|
if [ -z "${cc_path}" ]; then
|
||||||
cc_path="/usr/pkg/gcc13/bin/gcc"
|
cc_path="/usr/pkg/gcc14/bin/gcc"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mk_slunk() {
|
mk_slunk() {
|
||||||
@ -18,8 +18,6 @@ fi
|
|||||||
|
|
||||||
rm -rf "out" && mkdir -p "out"
|
rm -rf "out" && mkdir -p "out"
|
||||||
|
|
||||||
gmake CC="${cc_path}" clean
|
|
||||||
|
|
||||||
case "$(uname -m)" in
|
case "$(uname -m)" in
|
||||||
amd64)
|
amd64)
|
||||||
mk_slunk "x86_64" "x86-64" "nocona"
|
mk_slunk "x86_64" "x86-64" "nocona"
|
||||||
|
@ -18,8 +18,6 @@ fi
|
|||||||
|
|
||||||
rm -rf "out" && mkdir -p "out"
|
rm -rf "out" && mkdir -p "out"
|
||||||
|
|
||||||
gmake CC="${cc_path}" clean
|
|
||||||
|
|
||||||
case "$(uname -m)" in
|
case "$(uname -m)" in
|
||||||
amd64)
|
amd64)
|
||||||
mk_slunk "x86_64" "x86-64" "nocona"
|
mk_slunk "x86_64" "x86-64" "nocona"
|
||||||
|
@ -3,7 +3,7 @@ set -e
|
|||||||
cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../../.."
|
cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../../.."
|
||||||
|
|
||||||
if [ -z "${cc_path}" ]; then
|
if [ -z "${cc_path}" ]; then
|
||||||
cc_path="/usr/gcc/13/bin/gcc"
|
cc_path="/usr/gcc/14/bin/gcc"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mk_slunk() {
|
mk_slunk() {
|
||||||
@ -18,8 +18,6 @@ fi
|
|||||||
|
|
||||||
rm -rf "out" && mkdir -p "out"
|
rm -rf "out" && mkdir -p "out"
|
||||||
|
|
||||||
gmake CC="${cc_path}" clean
|
|
||||||
|
|
||||||
mk_slunk 32 "i686" "pentiumpro" "pentium3"
|
mk_slunk 32 "i686" "pentiumpro" "pentium3"
|
||||||
mk_slunk 64 "x86_64" "x86-64" "nocona"
|
mk_slunk 64 "x86_64" "x86-64" "nocona"
|
||||||
|
|
||||||
|
@ -23,12 +23,10 @@ fi
|
|||||||
|
|
||||||
mk_slunk() {
|
mk_slunk() {
|
||||||
make -B CC="${cc_path}" MARCH=${2} MTUNE=${3} STATIC=1 STRIP=1 FLTO=${use_flto}
|
make -B CC="${cc_path}" MARCH=${2} MTUNE=${3} STATIC=1 STRIP=1 FLTO=${use_flto}
|
||||||
cp -vf "frontend/bin/slunkcrypt" "out/_next_/slunkcrypt-${1}"
|
cp -vf "frontend/bin/slunkcrypt" "out/slunkcrypt-${1}"
|
||||||
}
|
}
|
||||||
|
|
||||||
mkdir -p "out/_next_"
|
mkdir -p "out"
|
||||||
|
|
||||||
make -B CC="${cc_path}" clean
|
|
||||||
|
|
||||||
case "${machine}" in
|
case "${machine}" in
|
||||||
x86_64*)
|
x86_64*)
|
||||||
@ -43,9 +41,9 @@ case "${machine}" in
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
if [[ "${machine}" == *"-cygwin" ]]; then
|
if [[ "${machine}" == *"-cygwin" ]]; then
|
||||||
cp -vfu "$(which cygwin1.dll)" "out/_next_"
|
cp -vfu "$(which cygwin1.dll)" "out"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
./etc/build/build_info.sh "${cc_path}" > "out/_next_/.build_info"
|
./etc/build/build_info.sh "${cc_path}" > "out/.build_info"
|
||||||
|
|
||||||
echo "Build completed successfully."
|
echo "Build completed successfully."
|
||||||
|
@ -34,7 +34,6 @@ Section
|
|||||||
!insertmacro PrintStatusMessage "Detecting operating system, please wait..."
|
!insertmacro PrintStatusMessage "Detecting operating system, please wait..."
|
||||||
${IfNot} ${AtLeastBuild} 7601
|
${IfNot} ${AtLeastBuild} 7601
|
||||||
MessageBox MB_ICONSTOP|MB_TOPMOST "This application runs on Windows 7 (SP1) or later!"
|
MessageBox MB_ICONSTOP|MB_TOPMOST "This application runs on Windows 7 (SP1) or later!"
|
||||||
ExecShell "open" "https://support.microsoft.com/en-us/windows/install-windows-7-service-pack-1-sp1-b3da2c0f-cdb6-0572-8596-bab972897f61"
|
|
||||||
Quit
|
Quit
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
/* Performance baseline (measured on Core i5 460M) */
|
||||||
|
#define PERF_FACTOR 104319.9
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Self-test routines
|
// Self-test routines
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
@ -216,6 +219,7 @@ int selftest_routine(const size_t thread_count, const int debug)
|
|||||||
|
|
||||||
const size_t total = ARRAY_SIZE(TEST_NONCE) * (ITERATIONS + (ITERATIONS * ARRAY_SIZE(TEST_STAGE)));
|
const size_t total = ARRAY_SIZE(TEST_NONCE) * (ITERATIONS + (ITERATIONS * ARRAY_SIZE(TEST_STAGE)));
|
||||||
size_t count = 0U;
|
size_t count = 0U;
|
||||||
|
uint64_t total_time = 0U;
|
||||||
|
|
||||||
FPRINTF(stderr, T("Self-test is in progress, please be patient... stage %2u/%2u "), 0U, (unsigned)total);
|
FPRINTF(stderr, T("Self-test is in progress, please be patient... stage %2u/%2u "), 0U, (unsigned)total);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
@ -229,10 +233,12 @@ int selftest_routine(const size_t thread_count, const int debug)
|
|||||||
{
|
{
|
||||||
FPRINTF(stderr, T("\b\b\b\b\b\b%2u/%2u "), (unsigned)++count, (unsigned)total);
|
FPRINTF(stderr, T("\b\b\b\b\b\b%2u/%2u "), (unsigned)++count, (unsigned)total);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
const uint64_t clk_start = clock_read();
|
||||||
if (run_testcase(TEST_STAGE[i].text, TEST_NONCE[k], TEST_STAGE[i].check_orig, TEST_STAGE[i].check_encr[j][k], ¶m) != EXIT_SUCCESS)
|
if (run_testcase(TEST_STAGE[i].text, TEST_NONCE[k], TEST_STAGE[i].check_orig, TEST_STAGE[i].check_encr[j][k], ¶m) != EXIT_SUCCESS)
|
||||||
{
|
{
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
total_time += clock_read() - clk_start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,14 +250,16 @@ int selftest_routine(const size_t thread_count, const int debug)
|
|||||||
{
|
{
|
||||||
FPRINTF(stderr, T("\b\b\b\b\b\b%2u/%2u "), (unsigned)++count, (unsigned)total);
|
FPRINTF(stderr, T("\b\b\b\b\b\b%2u/%2u "), (unsigned)++count, (unsigned)total);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
const uint64_t clk_start = clock_read();
|
||||||
if (run_stresstest(TEST_NONCE[j], ¶m) != EXIT_SUCCESS)
|
if (run_stresstest(TEST_NONCE[j], ¶m) != EXIT_SUCCESS)
|
||||||
{
|
{
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
total_time += clock_read() - clk_start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FPRINTF(stderr, T("\b\b\b\b\b\b%2u/%2u\n\nCompleted successfully.\n\n"), (unsigned)total, (unsigned)total);
|
FPRINTF(stderr, T("\b\b\b\b\b\b%2u/%2u\n\nCompleted successfully. (Score: %.0f)\n\n"), (unsigned)total, (unsigned)total, (double)clock_freq() / (double)total_time * PERF_FACTOR);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
@ -7,6 +7,6 @@
|
|||||||
<add key="DisableBusyIndicator" value="false"/>
|
<add key="DisableBusyIndicator" value="false"/>
|
||||||
<add key="ThreadCount" value="0"/>
|
<add key="ThreadCount" value="0"/>
|
||||||
<add key="KeepIncompleteFiles" value="false"/>
|
<add key="KeepIncompleteFiles" value="false"/>
|
||||||
<add key="LegacyCompat" value="false"/>
|
<add key="LegacyCompat" value="0"/>
|
||||||
</appSettings>
|
</appSettings>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
using com.muldersoft.slunkcrypt.gui.utils;
|
using com.muldersoft.slunkcrypt.gui.utils;
|
||||||
|
|
||||||
namespace com.muldersoft.slunkcrypt.gui.process
|
namespace com.muldersoft.slunkcrypt.gui.process
|
||||||
@ -87,7 +86,7 @@ namespace com.muldersoft.slunkcrypt.gui.process
|
|||||||
string.Equals(fileVersion.CompanyName, "Muldersoft", StringComparison.OrdinalIgnoreCase) &&
|
string.Equals(fileVersion.CompanyName, "Muldersoft", StringComparison.OrdinalIgnoreCase) &&
|
||||||
(fileVersion.FileMajorPart == appVersion.Major) && (fileVersion.FileMinorPart == appVersion.Minor))
|
(fileVersion.FileMajorPart == appVersion.Major) && (fileVersion.FileMinorPart == appVersion.Minor))
|
||||||
{
|
{
|
||||||
success = (fileVersion.FilePrivatePart >= appVersion.Revision);
|
success = ToVersion64(fileVersion.FileBuildPart, fileVersion.FilePrivatePart) >= ToVersion64(appVersion.Build, appVersion.Revision);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@ -101,5 +100,10 @@ namespace com.muldersoft.slunkcrypt.gui.process
|
|||||||
catch { }
|
catch { }
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ulong ToVersion64(int upper, int lower)
|
||||||
|
{
|
||||||
|
return (Convert.ToUInt64(upper) << 32) | Convert.ToUInt64(lower);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ namespace com.muldersoft.slunkcrypt.gui.process
|
|||||||
{
|
{
|
||||||
public enum Mode { Encrypt, Decrypt }
|
public enum Mode { Encrypt, Decrypt }
|
||||||
|
|
||||||
|
public enum Error { Checksum, Password }
|
||||||
|
|
||||||
public struct SlunkOptions
|
public struct SlunkOptions
|
||||||
{
|
{
|
||||||
public SlunkOptions(bool keepIncompleteFiles, int threadCount, bool enableLegacyCompat)
|
public SlunkOptions(bool keepIncompleteFiles, int threadCount, bool enableLegacyCompat)
|
||||||
@ -40,7 +42,14 @@ namespace com.muldersoft.slunkcrypt.gui.process
|
|||||||
private const bool ENABLE_DEBUG_LOGGING = false;
|
private const bool ENABLE_DEBUG_LOGGING = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private static readonly Regex RX_PROGRESS = new Regex(@"(\d+)\.(\d)%", RegexOptions.Compiled);
|
private static readonly Regex RX_PROGRESS = new Regex(@"(\d+)\.(\d)%", RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
||||||
|
|
||||||
|
private static readonly IReadOnlyDictionary<Error, Regex> RX_ERROR = new Dictionary<Error, Regex>
|
||||||
|
{
|
||||||
|
{ Error.Checksum, new Regex(@"\bChecksum\s+mismatch\s+detected\b", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant) },
|
||||||
|
{ Error.Password, new Regex(@"\bThe\s+given\s+passphrase\s+is\s+forbidden\s+as\s+a\s+precautionary\s+measure\b", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant) }
|
||||||
|
}
|
||||||
|
.ToReadOnlyDictionary();
|
||||||
|
|
||||||
private readonly FileStream m_executableFile;
|
private readonly FileStream m_executableFile;
|
||||||
|
|
||||||
@ -63,12 +72,15 @@ namespace com.muldersoft.slunkcrypt.gui.process
|
|||||||
{
|
{
|
||||||
throw new ArgumentException("Invalid SlunkCrypt parameters!");
|
throw new ArgumentException("Invalid SlunkCrypt parameters!");
|
||||||
}
|
}
|
||||||
Dictionary<string, string> environmentVariables = new Dictionary<string, string>();
|
Dictionary<string, string> environmentVariables = new Dictionary<string, string>
|
||||||
environmentVariables.Add("SLUNK_PASSPHRASE", password);
|
{
|
||||||
environmentVariables.Add("SLUNK_KEEP_INCOMPLETE", Convert.ToString(Convert.ToInt32(options.HasValue ? options.Value.keepIncompleteFiles : false)));
|
{ "SLUNK_PASSPHRASE", password },
|
||||||
environmentVariables.Add("SLUNK_THREADS", Convert.ToString(Math.Max(0, Math.Min(32, options.HasValue ? options.Value.threadCount : 0))));
|
{ "SLUNK_KEEP_INCOMPLETE", Convert.ToString(Convert.ToInt32(options.HasValue ? options.Value.keepIncompleteFiles : false)) },
|
||||||
environmentVariables.Add("SLUNK_LEGACY_COMPAT", Convert.ToString(Convert.ToInt32(options.HasValue ? options.Value.enableLegacyCompat : false)));
|
{ "SLUNK_THREADS", Convert.ToString(Math.Max(0, Math.Min(32, options.HasValue ? options.Value.threadCount : 0))) },
|
||||||
environmentVariables.Add("SLUNK_DEBUG_LOGGING", Convert.ToString(Convert.ToInt32(ENABLE_DEBUG_LOGGING)));
|
{ "SLUNK_LEGACY_COMPAT", Convert.ToString(Convert.ToInt32(options.HasValue ? options.Value.enableLegacyCompat : false)) },
|
||||||
|
{ "SLUNK_DEBUG_LOGGING", Convert.ToString(Convert.ToInt32(ENABLE_DEBUG_LOGGING)) }
|
||||||
|
};
|
||||||
|
ErrorState = null;
|
||||||
return await ExecAsnyc(m_executableFile.Name, new string[] { GetCommandString(mode), inputFile, outputFile }, Path.GetDirectoryName(outputFile), environmentVariables);
|
return await ExecAsnyc(m_executableFile.Name, new string[] { GetCommandString(mode), inputFile, outputFile }, Path.GetDirectoryName(outputFile), environmentVariables);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,23 +94,34 @@ namespace com.muldersoft.slunkcrypt.gui.process
|
|||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Error? ErrorState { get; private set; } = null;
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Internal methods
|
// Internal methods
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
protected override double ParseProgressString(ref string currentLine, bool stream)
|
protected override double ParseProgressString(ref string currentLine, bool stream)
|
||||||
{
|
{
|
||||||
double temp, result = double.NaN;
|
|
||||||
int index = int.MaxValue;
|
int index = int.MaxValue;
|
||||||
Match match = RX_PROGRESS.Match(currentLine);
|
double temp = double.NaN, result = double.NaN;
|
||||||
while (match.Success)
|
if (!ErrorState.HasValue)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<Error, Regex> errorRegex in RX_ERROR)
|
||||||
|
{
|
||||||
|
if (errorRegex.Value.IsMatch(currentLine))
|
||||||
|
{
|
||||||
|
ErrorState = errorRegex.Key;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Match match = RX_PROGRESS.Match(currentLine); match.Success; match = match.NextMatch())
|
||||||
{
|
{
|
||||||
if (TryParseProgressValue(match, out temp))
|
if (TryParseProgressValue(match, out temp))
|
||||||
{
|
{
|
||||||
result = temp;
|
result = double.IsNaN(result) ? temp : Math.Max(result, temp);
|
||||||
}
|
}
|
||||||
index = Math.Min(index, match.Index);
|
index = Math.Min(index, match.Index);
|
||||||
match = RX_PROGRESS.Match(currentLine, match.Index + match.Length);
|
|
||||||
}
|
}
|
||||||
if (index != int.MaxValue)
|
if (index != int.MaxValue)
|
||||||
{
|
{
|
||||||
|
@ -9,6 +9,6 @@ namespace com.muldersoft.slunkcrypt.gui.Properties
|
|||||||
{
|
{
|
||||||
public const string VERS_MAJOR = "1";
|
public const string VERS_MAJOR = "1";
|
||||||
public const string VERS_MINOR = "3";
|
public const string VERS_MINOR = "3";
|
||||||
public const string VERS_PATCH = "1";
|
public const string VERS_PATCH = "2";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,7 @@
|
|||||||
<DependentUpon>PasswordToggleBox.xaml</DependentUpon>
|
<DependentUpon>PasswordToggleBox.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Properties\_Version.cs" />
|
<Compile Include="Properties\_Version.cs" />
|
||||||
|
<Compile Include="Utilities\DictionaryHelper.cs" />
|
||||||
<Compile Include="Utilities\EnumHelper.cs" />
|
<Compile Include="Utilities\EnumHelper.cs" />
|
||||||
<Compile Include="Process\ExecutableHelper.cs" />
|
<Compile Include="Process\ExecutableHelper.cs" />
|
||||||
<Compile Include="Utilities\ApplicationConfig.cs" />
|
<Compile Include="Utilities\ApplicationConfig.cs" />
|
||||||
|
@ -49,7 +49,7 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
|
|
||||||
private volatile int m_isInitialized = 0;
|
private volatile int m_isInitialized = 0;
|
||||||
private volatile ModeOfOperation m_modeOfOperation = (ModeOfOperation)(-1);
|
private volatile ModeOfOperation m_modeOfOperation = (ModeOfOperation)(-1);
|
||||||
private volatile bool m_busyFlag = false, m_checksumError = false, m_processReceived = false, m_disableAnimation = false;
|
private volatile bool m_busyFlag = false, m_processReceived = false, m_disableAnimation = false;
|
||||||
private volatile SlunkCryptRunner m_processRunner = null;
|
private volatile SlunkCryptRunner m_processRunner = null;
|
||||||
private uint? m_menuId_disableAnimation = null, m_menuId_enableExpertMode = null;
|
private uint? m_menuId_disableAnimation = null, m_menuId_enableExpertMode = null;
|
||||||
|
|
||||||
@ -68,6 +68,10 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
m_dispatcherTimer.Interval = TimeSpan.FromMilliseconds(331);
|
m_dispatcherTimer.Interval = TimeSpan.FromMilliseconds(331);
|
||||||
m_logFileReadOnly = new ReadOnlyObservableCollection<string>(m_logFile);
|
m_logFileReadOnly = new ReadOnlyObservableCollection<string>(m_logFile);
|
||||||
m_disableAnimation = m_config.DisableBusyIndicator;
|
m_disableAnimation = m_config.DisableBusyIndicator;
|
||||||
|
if (m_config.LegacyCompat < 1)
|
||||||
|
{
|
||||||
|
Checkbox_Encrypt_LegacyCompat.Visibility = Checkbox_Decrypt_LegacyCompat.Visibility = Visibility.Collapsed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
@ -125,7 +129,7 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
{
|
{
|
||||||
Hint_SoftwareRendering.Visibility = Visibility.Visible;
|
Hint_SoftwareRendering.Visibility = Visibility.Visible;
|
||||||
}
|
}
|
||||||
if (m_config.LegacyCompat)
|
if (m_config.LegacyCompat > 1)
|
||||||
{
|
{
|
||||||
Checkbox_Encrypt_LegacyCompat.IsChecked = Checkbox_Decrypt_LegacyCompat.IsChecked = true;
|
Checkbox_Encrypt_LegacyCompat.IsChecked = Checkbox_Decrypt_LegacyCompat.IsChecked = true;
|
||||||
}
|
}
|
||||||
@ -273,10 +277,6 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
private void Process_OutputAvailable(string line, bool stderr)
|
private void Process_OutputAvailable(string line, bool stderr)
|
||||||
{
|
{
|
||||||
AppendLogFile(line);
|
AppendLogFile(line);
|
||||||
if (line.IndexOf("Checksum mismatch detected!", StringComparison.OrdinalIgnoreCase) >= 0)
|
|
||||||
{
|
|
||||||
m_checksumError = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Porcess_ProgressChanged(double progress)
|
private void Porcess_ProgressChanged(double progress)
|
||||||
@ -522,7 +522,7 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
|
|
||||||
private async Task ValidatePassword(string inputFilePath, string outputFilePath, PasswordToggleBox passwordEdit, CheckBox legacyCheckBox, SlunkProcessor processor, bool checkStrongPasswd)
|
private async Task ValidatePassword(string inputFilePath, string outputFilePath, PasswordToggleBox passwordEdit, CheckBox legacyCheckBox, SlunkProcessor processor, bool checkStrongPasswd)
|
||||||
{
|
{
|
||||||
bool enableLegacyCompat = legacyCheckBox.IsChecked.GetValueOrDefault();
|
bool enableLegacyCompat = (m_config.LegacyCompat > 0) && legacyCheckBox.IsChecked.GetValueOrDefault(m_config.LegacyCompat > 1);
|
||||||
string passwordStr;
|
string passwordStr;
|
||||||
if (string.IsNullOrEmpty(passwordStr = passwordEdit.Password) || (passwordStr.Length < MIN_PASSWD_LENGTH))
|
if (string.IsNullOrEmpty(passwordStr = passwordEdit.Password) || (passwordStr.Length < MIN_PASSWD_LENGTH))
|
||||||
{
|
{
|
||||||
@ -548,7 +548,7 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (enableLegacyCompat && (!m_config.LegacyCompat))
|
if (enableLegacyCompat && (m_config.LegacyCompat < 2))
|
||||||
{
|
{
|
||||||
if (MessageBox.Show(this, "Legacy compat-mode should not be used to encrypt new files!", "Legacy Compatibility", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel) != MessageBoxResult.OK)
|
if (MessageBox.Show(this, "Legacy compat-mode should not be used to encrypt new files!", "Legacy Compatibility", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel) != MessageBoxResult.OK)
|
||||||
{
|
{
|
||||||
@ -567,7 +567,7 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
ResetKeyboardFocus(this);
|
ResetKeyboardFocus(this);
|
||||||
SetProgress(double.PositiveInfinity);
|
SetProgress(double.PositiveInfinity);
|
||||||
ClearLogFile();
|
ClearLogFile();
|
||||||
Button_Decrypt_Toggle.IsChecked = Button_Encrypt_Toggle.IsChecked = m_checksumError = m_processReceived = false;
|
Button_Decrypt_Toggle.IsChecked = Button_Encrypt_Toggle.IsChecked = m_processReceived = false;
|
||||||
if (!await processor(inputFile, outputFile, password, enableLegacyCompat))
|
if (!await processor(inputFile, outputFile, password, enableLegacyCompat))
|
||||||
{
|
{
|
||||||
if (!m_config.KeepIncompleteFiles)
|
if (!m_config.KeepIncompleteFiles)
|
||||||
@ -583,10 +583,10 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
private async Task<bool> Encrypt(string inputFile, string outputFile, string password, bool enableLegacyCompat)
|
private async Task<bool> Encrypt(string inputFile, string outputFile, string password, bool enableLegacyCompat)
|
||||||
{
|
{
|
||||||
SetStatus("Please wait while the encryption process is initializing...");
|
SetStatus("Please wait while the encryption process is initializing...");
|
||||||
int? exitCode = await RunProcess(SlunkCryptRunner.Mode.Encrypt, inputFile, outputFile, password, enableLegacyCompat);
|
Tuple<int, SlunkCryptRunner.Error?> result = await RunProcess(SlunkCryptRunner.Mode.Encrypt, inputFile, outputFile, password, enableLegacyCompat);
|
||||||
if (exitCode.HasValue)
|
if (!ReferenceEquals(result, null))
|
||||||
{
|
{
|
||||||
if (exitCode.Value == 0)
|
if (result.Item1 == 0)
|
||||||
{
|
{
|
||||||
SetProgress(1);
|
SetProgress(1);
|
||||||
SetStatus("Completed: The file has been encrypted successfully.", Status.Success);
|
SetStatus("Completed: The file has been encrypted successfully.", Status.Success);
|
||||||
@ -594,8 +594,16 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetProgress(1, true);
|
switch (result.Item2)
|
||||||
|
{
|
||||||
|
case SlunkCryptRunner.Error.Password:
|
||||||
|
SetStatus("Error: The specified passphrase is forbidden! (contained in OWASP database)", Status.Failure);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
SetStatus("Error: Failed to enecrypt the file. Please see the log file for details!", Status.Failure);
|
SetStatus("Error: Failed to enecrypt the file. Please see the log file for details!", Status.Failure);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SetProgress(1, true);
|
||||||
SystemSounds.Hand.Play();
|
SystemSounds.Hand.Play();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -606,10 +614,10 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
private async Task<bool> Decrypt(string inputFile, string outputFile, string password, bool enableLegacyCompat)
|
private async Task<bool> Decrypt(string inputFile, string outputFile, string password, bool enableLegacyCompat)
|
||||||
{
|
{
|
||||||
SetStatus("Please wait while the decryption process is initializing...");
|
SetStatus("Please wait while the decryption process is initializing...");
|
||||||
int? exitCode = await RunProcess(SlunkCryptRunner.Mode.Decrypt, inputFile, outputFile, password, enableLegacyCompat);
|
Tuple<int, SlunkCryptRunner.Error?> result = await RunProcess(SlunkCryptRunner.Mode.Decrypt, inputFile, outputFile, password, enableLegacyCompat);
|
||||||
if (exitCode.HasValue)
|
if (!ReferenceEquals(result, null))
|
||||||
{
|
{
|
||||||
if (exitCode.Value == 0)
|
if (result.Item1 == 0)
|
||||||
{
|
{
|
||||||
SetStatus("Completed: The file has been decrypted successfully (checksum is correct).", Status.Success);
|
SetStatus("Completed: The file has been decrypted successfully (checksum is correct).", Status.Success);
|
||||||
SetProgress(1);
|
SetProgress(1);
|
||||||
@ -617,13 +625,14 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_checksumError)
|
switch (result.Item2)
|
||||||
{
|
{
|
||||||
|
case SlunkCryptRunner.Error.Checksum:
|
||||||
SetStatus("Error: Checksum mismatch detected! Wrong passphrase or corrupted file?", Status.Failure);
|
SetStatus("Error: Checksum mismatch detected! Wrong passphrase or corrupted file?", Status.Failure);
|
||||||
}
|
break;
|
||||||
else
|
default:
|
||||||
{
|
|
||||||
SetStatus("Error: Failed to decrypt the file. Please see the log file for details!", Status.Failure);
|
SetStatus("Error: Failed to decrypt the file. Please see the log file for details!", Status.Failure);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
SetProgress(1, true);
|
SetProgress(1, true);
|
||||||
SystemSounds.Hand.Play();
|
SystemSounds.Hand.Play();
|
||||||
@ -633,7 +642,7 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<int?> RunProcess(SlunkCryptRunner.Mode mode, string inputFile, string outputFile, string password, bool enableLegacyCompat)
|
private async Task<Tuple<int, SlunkCryptRunner.Error?>> RunProcess(SlunkCryptRunner.Mode mode, string inputFile, string outputFile, string password, bool enableLegacyCompat)
|
||||||
{
|
{
|
||||||
if (!ReferenceEquals(m_processRunner, null))
|
if (!ReferenceEquals(m_processRunner, null))
|
||||||
{
|
{
|
||||||
@ -647,7 +656,8 @@ namespace com.muldersoft.slunkcrypt.gui
|
|||||||
m_processRunner.OutputAvailable += Process_OutputAvailable;
|
m_processRunner.OutputAvailable += Process_OutputAvailable;
|
||||||
m_processRunner.ProgressChanged += Porcess_ProgressChanged;
|
m_processRunner.ProgressChanged += Porcess_ProgressChanged;
|
||||||
SetProcessPriority(ProcessPriorityClass.AboveNormal);
|
SetProcessPriority(ProcessPriorityClass.AboveNormal);
|
||||||
return await m_processRunner.ExecuteAsync(mode, inputFile, outputFile, password, options);
|
int exitCode = await m_processRunner.ExecuteAsync(mode, inputFile, outputFile, password, options);
|
||||||
|
return Tuple.Create(exitCode, m_processRunner.ErrorState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ProcessRunner.ProcessStartException err)
|
catch (ProcessRunner.ProcessStartException err)
|
||||||
|
@ -34,15 +34,15 @@ namespace com.muldersoft.slunkcrypt.gui.utils
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ComputeIfAbsent("ThreadCount", (key) => AppConfHelper.GetConfigValueAsInt32(key).GetValueOrDefault(0));
|
return ComputeIfAbsent("ThreadCount", (key) => Clamp(0, AppConfHelper.GetConfigValueAsInt32(key).GetValueOrDefault(0), 32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool LegacyCompat
|
public int LegacyCompat
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ComputeIfAbsent("LegacyCompat", (key) => AppConfHelper.GetConfigValueAsBool(key).GetValueOrDefault(false));
|
return ComputeIfAbsent("LegacyCompat", (key) => Clamp(0, AppConfHelper.GetConfigValueAsInt32(key).GetValueOrDefault(0), 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +60,11 @@ namespace com.muldersoft.slunkcrypt.gui.utils
|
|||||||
return Convert.ToBoolean(m_cache.GetOrAdd(name, (key) => Convert.ToInt32(valueFactory(key))));
|
return Convert.ToBoolean(m_cache.GetOrAdd(name, (key) => Convert.ToInt32(valueFactory(key))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static int Clamp(int min, int value, int max)
|
||||||
|
{
|
||||||
|
return (value < min) ? min : ((value > max) ? max : value);
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Helper class
|
// Helper class
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
@ -116,6 +121,14 @@ namespace com.muldersoft.slunkcrypt.gui.utils
|
|||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool boolean;
|
||||||
|
if (bool.TryParse(value.Trim(), out boolean))
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(boolean);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
18
gui/Utilities/DictionaryHelper.cs
Normal file
18
gui/Utilities/DictionaryHelper.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/******************************************************************************/
|
||||||
|
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
|
||||||
|
/* This work has been released under the CC0 1.0 Universal license! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace com.muldersoft.slunkcrypt.gui.utils
|
||||||
|
{
|
||||||
|
public static class DictionaryHelper
|
||||||
|
{
|
||||||
|
public static IReadOnlyDictionary<K, V> ToReadOnlyDictionary<K, V>(this IDictionary<K, V> dict)
|
||||||
|
{
|
||||||
|
return (dict is ReadOnlyDictionary<K, V>) ? ((ReadOnlyDictionary<K, V>)dict) : new ReadOnlyDictionary<K, V>(dict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,10 +23,11 @@ namespace com.muldersoft.slunkcrypt.gui.utils
|
|||||||
|
|
||||||
public static new string ToString()
|
public static new string ToString()
|
||||||
{
|
{
|
||||||
Version version = m_version.Value;
|
Version value = Version;
|
||||||
return string.Format(
|
string versionString = string.Format(
|
||||||
(version.Revision > 0) ? "Version {0:D}.{1:D}.{2:D}, built on {3}" : "Version {0:D}.{1:D}, built on {3}",
|
((value.Revision > 0) || (value.Build > 0)) ? ((value.Build > 0) ? "{0:D}.{1:D}.{2:D}.{3:D}" : "{0:D}.{1:D}.{3:D}") : "{0:D}.{1:D}",
|
||||||
version.Major, version.Minor, version.Revision, BuildDate.ToString("yyyy-MM-dd"));
|
value.Major, value.Minor, value.Build, value.Revision);
|
||||||
|
return string.Format("Version {0}, built on {1}", versionString, BuildDate.ToString("yyyy-MM-dd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
@ -8,6 +8,6 @@
|
|||||||
|
|
||||||
#define LIB_VERSION_MAJOR 1
|
#define LIB_VERSION_MAJOR 1
|
||||||
#define LIB_VERSION_MINOR 3
|
#define LIB_VERSION_MINOR 3
|
||||||
#define LIB_VERSION_PATCH 1
|
#define LIB_VERSION_PATCH 2
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user