Merge pull request #1 from ionspin/sample-continued
Migrate to own repo
This commit is contained in:
commit
548305644c
@ -54,7 +54,6 @@ macPublishToSnapshot:
|
|||||||
script:
|
script:
|
||||||
- ./macBuild.sh
|
- ./macBuild.sh
|
||||||
- ./macBuildAndPublishSnapshot-bindings.sh
|
- ./macBuildAndPublishSnapshot-bindings.sh
|
||||||
- ./macBuildAndPublishSnapshot-delegated.sh
|
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
tags:
|
tags:
|
||||||
@ -69,7 +68,6 @@ buildWindows:
|
|||||||
script:
|
script:
|
||||||
- $env:CHERE_INVOKING = 'yes'
|
- $env:CHERE_INVOKING = 'yes'
|
||||||
- C:\msys64\usr\bin\bash -lc "./windowsBuild-delegated.sh"
|
- C:\msys64\usr\bin\bash -lc "./windowsBuild-delegated.sh"
|
||||||
- C:\msys64\usr\bin\bash -lc "./windowsBuild-pure.sh"
|
|
||||||
tags:
|
tags:
|
||||||
- windowsX64
|
- windowsX64
|
||||||
|
|
||||||
@ -78,7 +76,6 @@ windowsPublishToSnapshot:
|
|||||||
script:
|
script:
|
||||||
- $env:CHERE_INVOKING = 'yes'
|
- $env:CHERE_INVOKING = 'yes'
|
||||||
- C:\msys64\usr\bin\bash -lc "./windowsBuildAndPublish-delegated.sh"
|
- C:\msys64\usr\bin\bash -lc "./windowsBuildAndPublish-delegated.sh"
|
||||||
- C:\msys64\usr\bin\bash -lc "./windowsBuildAndPublish-pure.sh"
|
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
tags:
|
tags:
|
||||||
|
197
.travis.yml
197
.travis.yml
@ -1,197 +0,0 @@
|
|||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: linux
|
|
||||||
name: linux
|
|
||||||
language: java
|
|
||||||
jdk: openjdk12
|
|
||||||
|
|
||||||
env:
|
|
||||||
KBUILD=linux
|
|
||||||
JAVA_OPTS=-Xmx2g
|
|
||||||
#skip ./gradlew assemble that is normally invoked in installation step
|
|
||||||
install:
|
|
||||||
- sudo apt-get update
|
|
||||||
- sudo apt-get -y install automake
|
|
||||||
script:
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./linuxBuild.sh; fi'
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./linuxBuildAndPublish.sh; fi'
|
|
||||||
# OSX macos
|
|
||||||
- os: osx
|
|
||||||
name: osx-mac
|
|
||||||
osx_image: xcode11.4
|
|
||||||
language: java
|
|
||||||
jdk: openjdk12
|
|
||||||
install: true
|
|
||||||
env:
|
|
||||||
KBUILD=linux
|
|
||||||
JAVA_OPTS=-Xmx2g
|
|
||||||
script:
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./macBuild-mac.sh; fi'
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./macBuildAndPublish-mac.sh; fi'
|
|
||||||
# OSX ios
|
|
||||||
- os: osx
|
|
||||||
name: osx-ios
|
|
||||||
osx_image: xcode11.4
|
|
||||||
language: java
|
|
||||||
jdk: openjdk12
|
|
||||||
install: true
|
|
||||||
env:
|
|
||||||
KBUILD=linux
|
|
||||||
JAVA_OPTS=-Xmx2g
|
|
||||||
script:
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./macBuild-ios.sh; fi'
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./macBuildAndPublish-ios.sh; fi'
|
|
||||||
# OSX watchos
|
|
||||||
- os: osx
|
|
||||||
name: osx-watchos
|
|
||||||
osx_image: xcode11.4
|
|
||||||
language: java
|
|
||||||
jdk: openjdk12
|
|
||||||
install: true
|
|
||||||
env:
|
|
||||||
KBUILD=linux
|
|
||||||
JAVA_OPTS=-Xmx2g
|
|
||||||
script:
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./macBuild-watchos.sh; fi'
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./macBuildAndPublish-watchos.sh; fi'
|
|
||||||
# OSX tvos
|
|
||||||
- os: osx
|
|
||||||
name: osx-tvos
|
|
||||||
osx_image: xcode11.4
|
|
||||||
language: java
|
|
||||||
jdk: openjdk12
|
|
||||||
install: true
|
|
||||||
env:
|
|
||||||
KBUILD=linux
|
|
||||||
JAVA_OPTS=-Xmx2g
|
|
||||||
script:
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./macBuild-tvos.sh; fi'
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./macBuildAndPublish-tvos.sh; fi'
|
|
||||||
|
|
||||||
# OSX macos PURE
|
|
||||||
- os: osx
|
|
||||||
name: osx-mac-pure
|
|
||||||
osx_image: xcode11.4
|
|
||||||
language: java
|
|
||||||
jdk: openjdk12
|
|
||||||
install: true
|
|
||||||
env:
|
|
||||||
KBUILD=linux
|
|
||||||
JAVA_OPTS=-Xmx2g
|
|
||||||
script:
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./macBuild-pure-mac.sh; fi'
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./macBuildAndPublish-pure-mac.sh; fi'
|
|
||||||
# OSX ios PURE
|
|
||||||
- os: osx
|
|
||||||
name: osx-ios-pure
|
|
||||||
osx_image: xcode11.4
|
|
||||||
language: java
|
|
||||||
jdk: openjdk12
|
|
||||||
install: true
|
|
||||||
env:
|
|
||||||
KBUILD=linux
|
|
||||||
JAVA_OPTS=-Xmx2g
|
|
||||||
script:
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./macBuild-pure-ios.sh; fi'
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./macBuildAndPublish-pure-ios.sh; fi'
|
|
||||||
# OSX watchos PURE
|
|
||||||
- os: osx
|
|
||||||
name: osx-watchos-pure
|
|
||||||
osx_image: xcode11.4
|
|
||||||
language: java
|
|
||||||
jdk: openjdk12
|
|
||||||
install: true
|
|
||||||
env:
|
|
||||||
KBUILD=linux
|
|
||||||
JAVA_OPTS=-Xmx2g
|
|
||||||
script:
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./macBuild-pure-watchos.sh; fi'
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./macBuildAndPublish-pure-watchos.sh; fi'
|
|
||||||
# OSX tvos PURE
|
|
||||||
- os: osx
|
|
||||||
name: osx-tvos-pure
|
|
||||||
osx_image: xcode11.4
|
|
||||||
language: java
|
|
||||||
jdk: openjdk12
|
|
||||||
install: true
|
|
||||||
env:
|
|
||||||
KBUILD=linux
|
|
||||||
JAVA_OPTS=-Xmx2g
|
|
||||||
script:
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./macBuild-pure-tvos.sh; fi'
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./macBuildAndPublish-pure-tvos.sh; fi'
|
|
||||||
|
|
||||||
- os: windows
|
|
||||||
name: windows-pure
|
|
||||||
language: shell
|
|
||||||
jdk: openjdk12
|
|
||||||
env:
|
|
||||||
- GRAVIS="https://raw.githubusercontent.com/DanySK/Gravis-CI/master/"
|
|
||||||
- JAVA_OPTS=-Xmx2g
|
|
||||||
- JDK="adopt-openj9@1.11"
|
|
||||||
before_install:
|
|
||||||
- curl "${GRAVIS}.install-jdk-travis.sh" --output ~/.install-jdk-travis.sh
|
|
||||||
- source ~/.install-jdk-travis.sh
|
|
||||||
install: true
|
|
||||||
script:
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then $shell ./windowsBuild-pure.sh; fi'
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then ./windowsBuildAndPublish-pure.sh; fi'
|
|
||||||
- os: windows
|
|
||||||
name: windows-delegated
|
|
||||||
language: shell
|
|
||||||
jdk: openjdk12
|
|
||||||
env:
|
|
||||||
- GRAVIS="https://raw.githubusercontent.com/DanySK/Gravis-CI/master/"
|
|
||||||
- JAVA_OPTS=-Xmx2g
|
|
||||||
- JDK="adopt-openj9@1.11"
|
|
||||||
before_install:
|
|
||||||
- curl "${GRAVIS}.install-jdk-travis.sh" --output ~/.install-jdk-travis.sh
|
|
||||||
- source ~/.install-jdk-travis.sh
|
|
||||||
- |-
|
|
||||||
case $TRAVIS_OS_NAME in
|
|
||||||
windows)
|
|
||||||
[[ ! -f C:/tools/msys64/msys2_shell.cmd ]] && rm -rf C:/tools/msys64
|
|
||||||
choco uninstall -y mingw
|
|
||||||
choco upgrade --no-progress -y msys2 bazel
|
|
||||||
export msys2='cmd //C RefreshEnv.cmd '
|
|
||||||
export msys2+='& set MSYS=winsymlinks:nativestrict '
|
|
||||||
export msys2+='& C:\\tools\\msys64\\msys2_shell.cmd -defterm -no-start'
|
|
||||||
export shell="$msys2 -mingw64 -full-path -here -c \$\* --"
|
|
||||||
export msys2+=" -msys2 -c \$\* --"
|
|
||||||
$msys2 pacman --sync --noconfirm --needed \
|
|
||||||
autoconf \
|
|
||||||
automake \
|
|
||||||
mingw-w64-x86_64-libtool \
|
|
||||||
mingw-w64-x86_64-toolchain \
|
|
||||||
perl \
|
|
||||||
unzip
|
|
||||||
taskkill //IM gpg-agent.exe //F
|
|
||||||
export CPPFLAGS=-D__USE_MINGW_ANSI_STDIO=1
|
|
||||||
export PATH=/C/tools/msys64/mingw64/bin:$PATH
|
|
||||||
export GNU_MAKE=mingw32-make
|
|
||||||
export MAKE=mingw32-make
|
|
||||||
export AR=gcc-ar
|
|
||||||
export RANLIB=gcc-ranlib
|
|
||||||
export COVERITY_SCAN_BRANCH_PATTERN=disable_coverity_scan
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
- export GIT=git
|
|
||||||
- g++ --version
|
|
||||||
- $GNU_MAKE --version
|
|
||||||
- $GIT --version
|
|
||||||
install: true
|
|
||||||
before_cache:
|
|
||||||
- $msys2 pacman --sync --clean --noconfirm
|
|
||||||
script:
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then $shell ./windowsBuild-delegated.sh; fi'
|
|
||||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then $shell ./windowsBuildAndPublish-delegated.sh; fi'
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.m2/
|
|
||||||
- $HOME/.gradle
|
|
||||||
- $HOME/.konan
|
|
||||||
- $HOME/AppData/Local/Temp/chocolatey
|
|
||||||
- /C/tools/msys64
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
[](https://gitlab.com/ionspin-github-ci/kotlin-multiplatform-crypto-ci/-/commits/master)
|
[](https://gitlab.com/ionspin-github-ci/kotlin-multiplatform-libsodium/-/commits/master)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -108,6 +108,7 @@ And here is the usage sample
|
|||||||
|
|
||||||
The functions are mapped from libsodium to kotiln objects, so `crypto_secretstream_xchacha20poly1305_init_push` becomes
|
The functions are mapped from libsodium to kotiln objects, so `crypto_secretstream_xchacha20poly1305_init_push` becomes
|
||||||
`SecretStream.xChaCha20Poly1305InitPush`
|
`SecretStream.xChaCha20Poly1305InitPush`
|
||||||
|

|
||||||
|
|
||||||
At the moment you should refer to original libsodium documentation for instructions on how to use the library
|
At the moment you should refer to original libsodium documentation for instructions on how to use the library
|
||||||
|
|
||||||
@ -139,6 +140,7 @@ Currently supported native platforms:
|
|||||||
- Android testing
|
- Android testing
|
||||||
- Fix browser testing, both locally and in CI/CD
|
- Fix browser testing, both locally and in CI/CD
|
||||||
- LobsodiumUtil `unpad` and `fromBase64` native implementations use a nasty hack to support shared native sourceset. The hack either needs to be removed and replaced with another solution or additional safeguards need to be added.
|
- LobsodiumUtil `unpad` and `fromBase64` native implementations use a nasty hack to support shared native sourceset. The hack either needs to be removed and replaced with another solution or additional safeguards need to be added.
|
||||||
|
- Complete exposing libsodium constants
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
object Versions {
|
object Versions {
|
||||||
val kotlinCoroutines = "1.3.9"
|
val kotlinCoroutines = "1.4.1"
|
||||||
val kotlin = "1.4.10"
|
val kotlin = "1.4.20"
|
||||||
val kotlinSerialization = "1.0.0"
|
val kotlinSerialization = "1.0.1"
|
||||||
val kotlinSerializationPlugin = "1.4.10"
|
val kotlinSerializationPlugin = "1.4.10"
|
||||||
val atomicfu = "0.14.3-M2-2-SNAPSHOT" //NOTE: my linux arm32 and arm64 build
|
val atomicfu = "0.14.3-M2-2-SNAPSHOT" //NOTE: my linux arm32 and arm64 build
|
||||||
val nodePlugin = "1.3.0"
|
val nodePlugin = "1.3.0"
|
||||||
val dokkaPlugin = "1.4.0-rc"
|
val dokkaPlugin = "1.4.0"
|
||||||
val taskTreePlugin = "1.5"
|
val taskTreePlugin = "1.5"
|
||||||
val kotlinBigNumVersion = "0.2.2"
|
val kotlinBigNumVersion = "0.2.2"
|
||||||
val lazySodium = "4.3.1-SNAPSHOT"
|
val lazySodium = "4.3.1-SNAPSHOT"
|
||||||
|
91
doc/res/libsodium_api_mapping.svg
Normal file
91
doc/res/libsodium_api_mapping.svg
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="297mm"
|
||||||
|
height="210mm"
|
||||||
|
viewBox="0 0 297 210"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
|
||||||
|
sodipodi:docname="libsodium_api_mapping.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.7"
|
||||||
|
inkscape:cx="554.56493"
|
||||||
|
inkscape:cy="538.66625"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1276"
|
||||||
|
inkscape:window-height="1396"
|
||||||
|
inkscape:window-x="3840"
|
||||||
|
inkscape:window-y="20"
|
||||||
|
inkscape:window-maximized="0" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;word-spacing:0px;stroke-width:0.264583"
|
||||||
|
x="9.5235968"
|
||||||
|
y="64.991554"
|
||||||
|
id="text12"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan10"
|
||||||
|
x="9.5235968"
|
||||||
|
y="64.991554"
|
||||||
|
style="stroke-width:0.264583"><tspan
|
||||||
|
style="fill:#ff0000"
|
||||||
|
id="tspan18">crypto</tspan>_<tspan
|
||||||
|
style="fill:#008000"
|
||||||
|
id="tspan20">secretstream</tspan>_<tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan22">xchacha20poly1305</tspan>_<tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan28">init</tspan>_<tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan30">push</tspan></tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;word-spacing:0px;stroke-width:0.264583"
|
||||||
|
x="47.202728"
|
||||||
|
y="94.062126"
|
||||||
|
id="text16"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan14"
|
||||||
|
x="47.202728"
|
||||||
|
y="94.062126"
|
||||||
|
style="stroke-width:0.264583"><tspan
|
||||||
|
style="fill:#008000"
|
||||||
|
id="tspan34">SecretStream</tspan>.<tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan32">xChaCha20Poly1305InitPush</tspan></tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
@ -15,10 +15,8 @@ fi
|
|||||||
./makeLinuxArm64.sh
|
./makeLinuxArm64.sh
|
||||||
#now we can do the delegated build
|
#now we can do the delegated build
|
||||||
cd ..
|
cd ..
|
||||||
./gradlew multiplatform-crypto-delegated:build
|
|
||||||
#build libsodium bindings
|
#build libsodium bindings
|
||||||
./gradlew multiplatform-crypto-libsodium-bindings:build
|
./gradlew multiplatform-crypto-libsodium-bindings:build
|
||||||
#and finally pure build
|
|
||||||
./gradlew multiplatform-crypto:build
|
|
||||||
set +e
|
set +e
|
||||||
|
|
||||||
|
@ -15,11 +15,9 @@ fi
|
|||||||
./makeLinuxArm64.sh
|
./makeLinuxArm64.sh
|
||||||
#now we can do the delegated build
|
#now we can do the delegated build
|
||||||
cd ..
|
cd ..
|
||||||
./gradlew multiplatform-crypto-delegated:build
|
|
||||||
#build libsodium bindings
|
#build libsodium bindings
|
||||||
./gradlew multiplatform-crypto-libsodium-bindings:build
|
./gradlew multiplatform-crypto-libsodium-bindings:build
|
||||||
#and finally pure build
|
|
||||||
./gradlew multiplatform-crypto:build
|
|
||||||
./gradlew publishJvmPublicationToSnapshotRepository publishJsPublicationToSnapshotRepository \
|
./gradlew publishJvmPublicationToSnapshotRepository publishJsPublicationToSnapshotRepository \
|
||||||
publishKotlinMultiplatformPublicationToSnapshotRepository publishLinuxX64PublicationToSnapshotRepository \
|
publishKotlinMultiplatformPublicationToSnapshotRepository publishLinuxX64PublicationToSnapshotRepository \
|
||||||
publishLinuxArm64PublicationToSnapshotRepository publishMetadataPublicationToSnapshotRepository
|
publishLinuxArm64PublicationToSnapshotRepository publishMetadataPublicationToSnapshotRepository
|
||||||
|
@ -8,10 +8,6 @@ cd sodiumWrapper
|
|||||||
./makeIos.sh
|
./makeIos.sh
|
||||||
#now we can do the delegated build of ios and macos libraries
|
#now we can do the delegated build of ios and macos libraries
|
||||||
cd ..
|
cd ..
|
||||||
./gradlew multiplatform-crypto-delegated:iosArm32MainKlibrary multiplatform-crypto-delegated:iosArm32TestKlibrary \
|
|
||||||
multiplatform-crypto-delegated:iosArm64MainKlibrary multiplatform-crypto-delegated:iosArm64TestKlibrary \
|
|
||||||
multiplatform-crypto-delegated:iosX64MainKlibrary multiplatform-crypto-delegated:iosX64TestKlibrary
|
|
||||||
./gradlew multiplatform-crypto-delegated:iosX64Test
|
|
||||||
|
|
||||||
./gradlew multiplatform-crypto-libsodium-bindings:iosArm32MainKlibrary multiplatform-crypto-libsodium-bindings:iosArm32TestKlibrary \
|
./gradlew multiplatform-crypto-libsodium-bindings:iosArm32MainKlibrary multiplatform-crypto-libsodium-bindings:iosArm32TestKlibrary \
|
||||||
multiplatform-crypto-libsodium-bindings:iosArm64MainKlibrary multiplatform-crypto-libsodium-bindings:iosArm64TestKlibrary \
|
multiplatform-crypto-libsodium-bindings:iosArm64MainKlibrary multiplatform-crypto-libsodium-bindings:iosArm64TestKlibrary \
|
||||||
|
@ -8,9 +8,6 @@ cd sodiumWrapper
|
|||||||
./makeIos.sh
|
./makeIos.sh
|
||||||
#now we can do the delegated build of ios and macos libraries
|
#now we can do the delegated build of ios and macos libraries
|
||||||
cd ..
|
cd ..
|
||||||
./gradlew multiplatform-crypto-delegated:macosX64MainKlibrary multiplatform-crypto-delegated:macosX64TestKlibrary
|
|
||||||
./gradlew multiplatform-crypto-delegated:macosX64Test
|
|
||||||
|
|
||||||
./gradlew multiplatform-crypto-libsodium-bindings:macosX64MainKlibrary multiplatform-crypto-libsodium-bindings:macosX64TestKlibrary
|
./gradlew multiplatform-crypto-libsodium-bindings:macosX64MainKlibrary multiplatform-crypto-libsodium-bindings:macosX64TestKlibrary
|
||||||
./gradlew multiplatform-crypto-libsodium-bindings:macosX64Test
|
./gradlew multiplatform-crypto-libsodium-bindings:macosX64Test
|
||||||
set +e
|
set +e
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
set -e
|
|
||||||
#!/bin/sh
|
|
||||||
./gradlew multiplatform-crypto-api:build
|
|
||||||
./gradlew multiplatform-crypto:iosArm32MainKlibrary multiplatform-crypto:iosArm32TestKlibrary \
|
|
||||||
multiplatform-crypto:iosArm64MainKlibrary multiplatform-crypto:iosArm64TestKlibrary \
|
|
||||||
multiplatform-crypto:iosX64MainKlibrary multiplatform-crypto:iosX64TestKlibrary
|
|
||||||
./gradlew multiplatform-crypto:iosX64Test
|
|
||||||
|
|
||||||
set +e
|
|
@ -1,7 +0,0 @@
|
|||||||
set -e
|
|
||||||
#!/bin/sh
|
|
||||||
./gradlew multiplatform-crypto-api:build
|
|
||||||
./gradlew multiplatform-crypto:macosX64MainKlibrary multiplatform-crypto:macosX64TestKlibrary
|
|
||||||
./gradlew multiplatform-crypto:macosX64Test
|
|
||||||
|
|
||||||
set +e
|
|
@ -1,7 +0,0 @@
|
|||||||
set -e
|
|
||||||
#!/bin/sh
|
|
||||||
./gradlew multiplatform-crypto-api:build
|
|
||||||
./gradlew multiplatform-crypto:tvosArm64MainKlibrary multiplatform-crypto:tvosArm64TestKlibrary \
|
|
||||||
multiplatform-crypto:tvosX64MainKlibrary multiplatform-crypto:tvosX64TestKlibrary
|
|
||||||
./gradlew multiplatform-crypto:tvosX64Test
|
|
||||||
set +e
|
|
@ -1,8 +0,0 @@
|
|||||||
set -e
|
|
||||||
#!/bin/sh
|
|
||||||
./gradlew multiplatform-crypto-api:build
|
|
||||||
./gradlew multiplatform-crypto:watchosArm32MainKlibrary multiplatform-crypto:watchosArm32TestKlibrary \
|
|
||||||
multiplatform-crypto:watchosArm64MainKlibrary multiplatform-crypto:watchosArm64TestKlibrary \
|
|
||||||
multiplatform-crypto:watchosX86MainKlibrary multiplatform-crypto:watchosX86TestKlibrary
|
|
||||||
./gradlew multiplatform-crypto:watchosX86Test
|
|
||||||
set +e
|
|
@ -7,9 +7,6 @@ cd sodiumWrapper
|
|||||||
./makeTvos.sh
|
./makeTvos.sh
|
||||||
#now we can do the delegated build of ios and macos libraries
|
#now we can do the delegated build of ios and macos libraries
|
||||||
cd ..
|
cd ..
|
||||||
./gradlew multiplatform-crypto-delegated:tvosArm64MainKlibrary multiplatform-crypto-delegated:tvosArm64TestKlibrary \
|
|
||||||
multiplatform-crypto-delegated:tvosX64MainKlibrary multiplatform-crypto-delegated:tvosX64TestKlibrary
|
|
||||||
./gradlew multiplatform-crypto-delegated:tvosX64Test
|
|
||||||
|
|
||||||
./gradlew multiplatform-crypto-libsodium-bindings:tvosArm64MainKlibrary multiplatform-crypto-libsodium-bindings:tvosArm64TestKlibrary \
|
./gradlew multiplatform-crypto-libsodium-bindings:tvosArm64MainKlibrary multiplatform-crypto-libsodium-bindings:tvosArm64TestKlibrary \
|
||||||
multiplatform-crypto-libsodium-bindings:tvosX64MainKlibrary multiplatform-crypto-libsodium-bindings:tvosX64TestKlibrary
|
multiplatform-crypto-libsodium-bindings:tvosX64MainKlibrary multiplatform-crypto-libsodium-bindings:tvosX64TestKlibrary
|
||||||
|
@ -7,10 +7,6 @@ cd sodiumWrapper
|
|||||||
./makeWatchos.sh
|
./makeWatchos.sh
|
||||||
#now we can do the delegated build of ios and macos libraries
|
#now we can do the delegated build of ios and macos libraries
|
||||||
cd ..
|
cd ..
|
||||||
./gradlew multiplatform-crypto-delegated:watchosArm32MainKlibrary multiplatform-crypto-delegated:watchosArm32TestKlibrary \
|
|
||||||
multiplatform-crypto-delegated:watchosArm64MainKlibrary multiplatform-crypto-delegated:watchosArm64TestKlibrary \
|
|
||||||
multiplatform-crypto-delegated:watchosX86MainKlibrary multiplatform-crypto-delegated:watchosX86TestKlibrary
|
|
||||||
./gradlew multiplatform-crypto-delegated:watchosX86Test
|
|
||||||
|
|
||||||
./gradlew multiplatform-crypto-libsodium-bindings:watchosArm32MainKlibrary multiplatform-crypto-libsodium-bindings:watchosArm32TestKlibrary \
|
./gradlew multiplatform-crypto-libsodium-bindings:watchosArm32MainKlibrary multiplatform-crypto-libsodium-bindings:watchosArm32TestKlibrary \
|
||||||
multiplatform-crypto-libsodium-bindings:watchosArm64MainKlibrary multiplatform-crypto-libsodium-bindings:watchosArm64TestKlibrary \
|
multiplatform-crypto-libsodium-bindings:watchosArm64MainKlibrary multiplatform-crypto-libsodium-bindings:watchosArm64TestKlibrary \
|
||||||
|
@ -8,9 +8,6 @@ cd sodiumWrapper
|
|||||||
./makeIosWatchosTvos.sh
|
./makeIosWatchosTvos.sh
|
||||||
#now we can do the delegated build
|
#now we can do the delegated build
|
||||||
cd ..
|
cd ..
|
||||||
./gradlew multiplatform-crypto-delegated:build
|
|
||||||
#pure build
|
|
||||||
./gradlew multiplatform-crypto:build
|
|
||||||
#libsodium bindings
|
#libsodium bindings
|
||||||
./gradlew multiplatform-crypto-libsodium-bindings:build
|
./gradlew multiplatform-crypto-libsodium-bindings:build
|
||||||
set +e
|
set +e
|
||||||
|
@ -8,9 +8,6 @@ cd sodiumWrapper
|
|||||||
./makeIos.sh
|
./makeIos.sh
|
||||||
#now we can do the delegated build of ios and macos libraries
|
#now we can do the delegated build of ios and macos libraries
|
||||||
cd ..
|
cd ..
|
||||||
./gradlew multiplatform-crypto-delegated:publishIosArm32PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto-delegated:publishIosArm64PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto-delegated:publishIosX64PublicationToSnapshotRepository
|
|
||||||
|
|
||||||
./gradlew multiplatform-crypto-libsodium-bindings:publishIosArm32PublicationToSnapshotRepository \
|
./gradlew multiplatform-crypto-libsodium-bindings:publishIosArm32PublicationToSnapshotRepository \
|
||||||
multiplatform-crypto-libsodium-bindings:publishIosArm64PublicationToSnapshotRepository \
|
multiplatform-crypto-libsodium-bindings:publishIosArm64PublicationToSnapshotRepository \
|
||||||
|
@ -7,7 +7,6 @@ cd sodiumWrapper
|
|||||||
./makeMacosX86-64.sh
|
./makeMacosX86-64.sh
|
||||||
#now we can do the delegated build of ios and macos libraries
|
#now we can do the delegated build of ios and macos libraries
|
||||||
cd ..
|
cd ..
|
||||||
./gradlew multiplatform-crypto-delegated:publishMacosX64PublicationToSnapshotRepository
|
|
||||||
|
|
||||||
./gradlew multiplatform-crypto-libsodium-bindings:publishMacosX64PublicationToSnapshotRepository
|
./gradlew multiplatform-crypto-libsodium-bindings:publishMacosX64PublicationToSnapshotRepository
|
||||||
set +e
|
set +e
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
set -e
|
|
||||||
#!/bin/sh
|
|
||||||
#this will hopefully download all konan dependancies that we use in the build scripts
|
|
||||||
./gradlew multiplatform-crypto-api:build
|
|
||||||
./gradlew multiplatform-crypto:publishIosArm32PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto:publishIosArm64PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto:publishIosX64PublicationToSnapshotRepository
|
|
||||||
set +e
|
|
@ -1,6 +0,0 @@
|
|||||||
set -e
|
|
||||||
#!/bin/sh
|
|
||||||
#this will hopefully download all konan dependancies that we use in the build scripts
|
|
||||||
./gradlew multiplatform-crypto-api:build
|
|
||||||
./gradlew multiplatform-crypto:publishMacosX64PublicationToSnapshotRepository
|
|
||||||
set +e
|
|
@ -1,8 +0,0 @@
|
|||||||
set -e
|
|
||||||
#!/bin/sh
|
|
||||||
#this will hopefully download all konan dependancies that we use in the build scripts
|
|
||||||
./gradlew multiplatform-crypto-api:build
|
|
||||||
./gradlew multiplatform-crypto:publishTvosArm64PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto:publishTvosX64PublicationToSnapshotRepository
|
|
||||||
|
|
||||||
set +e
|
|
@ -1,8 +0,0 @@
|
|||||||
set -e
|
|
||||||
#!/bin/sh
|
|
||||||
#this will hopefully download all konan dependancies that we use in the build scripts
|
|
||||||
./gradlew multiplatform-crypto-api:build
|
|
||||||
./gradlew multiplatform-crypto:publishWatchosArm32PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto:publishWatchosArm64PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto:publishWatchosX86PublicationToSnapshotRepository
|
|
||||||
set +e
|
|
@ -1,8 +0,0 @@
|
|||||||
set -e
|
|
||||||
#!/bin/sh
|
|
||||||
#this will hopefully download all konan dependancies that we use in the build scripts
|
|
||||||
./gradlew multiplatform-crypto-api:build
|
|
||||||
./gradlew multiplatform-crypto:publishTvosArm64PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto:publishTvosX64PublicationToSnapshotRepository
|
|
||||||
|
|
||||||
set +e
|
|
@ -7,9 +7,6 @@ cd sodiumWrapper
|
|||||||
./makeWatchos.sh
|
./makeWatchos.sh
|
||||||
#now we can do the delegated build of ios and macos libraries
|
#now we can do the delegated build of ios and macos libraries
|
||||||
cd ..
|
cd ..
|
||||||
./gradlew multiplatform-crypto-delegated:publishWatchosArm32PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto-delegated:publishWatchosArm64PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto-delegated:publishWatchosX86PublicationToSnapshotRepository
|
|
||||||
|
|
||||||
./gradlew multiplatform-crypto-libsodium-bindings:publishWatchosArm32PublicationToSnapshotRepository \
|
./gradlew multiplatform-crypto-libsodium-bindings:publishWatchosArm32PublicationToSnapshotRepository \
|
||||||
multiplatform-crypto-libsodium-bindings:publishWatchosArm64PublicationToSnapshotRepository \
|
multiplatform-crypto-libsodium-bindings:publishWatchosArm64PublicationToSnapshotRepository \
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
set -e
|
|
||||||
#!/bin/sh
|
|
||||||
./gradlew multiplatform-crypto-delegated:publishMacosX64PublicationToSnapshotRepository
|
|
||||||
|
|
||||||
./gradlew multiplatform-crypto-delegated:publishIosArm32PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto-delegated:publishIosArm64PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto-delegated:publishIosX64PublicationToSnapshotRepository
|
|
||||||
|
|
||||||
./gradlew multiplatform-crypto-delegated:publishWatchosArm32PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto-delegated:publishWatchosArm64PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto-delegated:publishWatchosX86PublicationToSnapshotRepository
|
|
||||||
|
|
||||||
./gradlew multiplatform-crypto-delegated:publishTvosArm64PublicationToSnapshotRepository \
|
|
||||||
multiplatform-crypto-delegated:publishTvosX64PublicationToSnapshotRepository
|
|
||||||
set +e
|
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest
|
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest
|
||||||
|
import org.jetbrains.dokka.Platform
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin(PluginsDeps.multiplatform)
|
kotlin(PluginsDeps.multiplatform)
|
||||||
@ -275,9 +276,9 @@ tasks {
|
|||||||
dokkaJavadoc {
|
dokkaJavadoc {
|
||||||
println("Dokka !")
|
println("Dokka !")
|
||||||
dokkaSourceSets {
|
dokkaSourceSets {
|
||||||
create("commonMain") {
|
named("commonMain") {
|
||||||
displayName = "common"
|
displayName.set("common")
|
||||||
platform = "common"
|
platform.set(Platform.common)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,697 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:Suppress("UnstableApiUsage")
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
kotlin(PluginsDeps.multiplatform)
|
|
||||||
id(PluginsDeps.mavenPublish)
|
|
||||||
id(PluginsDeps.signing)
|
|
||||||
id(PluginsDeps.node) version Versions.nodePlugin
|
|
||||||
id(PluginsDeps.dokka)
|
|
||||||
id(PluginsDeps.taskTree) version Versions.taskTreePlugin
|
|
||||||
}
|
|
||||||
|
|
||||||
val sonatypeStaging = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
|
||||||
val sonatypeSnapshots = "https://oss.sonatype.org/content/repositories/snapshots/"
|
|
||||||
|
|
||||||
val sonatypePassword: String? by project
|
|
||||||
|
|
||||||
val sonatypeUsername: String? by project
|
|
||||||
|
|
||||||
val sonatypePasswordEnv: String? = System.getenv()["SONATYPE_PASSWORD"]
|
|
||||||
val sonatypeUsernameEnv: String? = System.getenv()["SONATYPE_USERNAME"]
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
jcenter()
|
|
||||||
|
|
||||||
}
|
|
||||||
group = ReleaseInfo.group
|
|
||||||
version = ReleaseInfo.version
|
|
||||||
|
|
||||||
val ideaActive = isInIdea()
|
|
||||||
println("Idea active: $ideaActive")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
kotlin {
|
|
||||||
val hostOsName = getHostOsName()
|
|
||||||
runningOnLinuxx86_64 {
|
|
||||||
println("Configuring Linux X86-64 targets")
|
|
||||||
jvm()
|
|
||||||
js {
|
|
||||||
browser {
|
|
||||||
testTask {
|
|
||||||
isRunningInGitlabCi {
|
|
||||||
enabled = false //Until I sort out testing on travis
|
|
||||||
}
|
|
||||||
useKarma {
|
|
||||||
useChrome()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nodejs {
|
|
||||||
testTask {
|
|
||||||
useMocha() {
|
|
||||||
timeout = "10s"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
linuxX64() {
|
|
||||||
compilations.getByName("main") {
|
|
||||||
val libsodiumCinterop by cinterops.creating {
|
|
||||||
defFile(project.file("src/nativeInterop/cinterop/libsodium.def"))
|
|
||||||
compilerOpts.add("-I${project.rootDir}/sodiumWrapper/static-linux-x86-64/include/")
|
|
||||||
}
|
|
||||||
kotlinOptions.freeCompilerArgs = listOf(
|
|
||||||
"-include-binary", "${project.rootDir}/sodiumWrapper/static-linux-x86-64/lib/libsodium.a"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
binaries {
|
|
||||||
staticLib {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
linuxArm64() {
|
|
||||||
binaries {
|
|
||||||
staticLib {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Linux 32 is using target-sysroot-2-raspberrypi which is missing getrandom and explicit_bzero in stdlib
|
|
||||||
// so konanc can't build klib because getrandom missing will cause sodium_misuse()
|
|
||||||
// ld.lld: error: undefined symbol: explicit_bzero
|
|
||||||
// >>> referenced by utils.c
|
|
||||||
// >>> libsodium_la-utils.o:(sodium_memzero) in archive /tmp/included11051337748775083797/libsodium.a
|
|
||||||
//
|
|
||||||
// ld.lld: error: undefined symbol: getrandom
|
|
||||||
// >>> referenced by randombytes_sysrandom.c
|
|
||||||
// >>> libsodium_la-randombytes_sysrandom.o:(_randombytes_linux_getrandom) in archive /tmp/included11051337748775083797/libsodium.a
|
|
||||||
|
|
||||||
// linuxArm32Hfp() {
|
|
||||||
// binaries {
|
|
||||||
// staticLib {
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// compilations.getByName("main") {
|
|
||||||
// val libsodiumCinterop by cinterops.creating {
|
|
||||||
// defFile(project.file("src/nativeInterop/cinterop/libsodium.def"))
|
|
||||||
// compilerOpts.add("-I${project.rootDir}/sodiumWrapper/static-arm32/include/")
|
|
||||||
// }
|
|
||||||
// kotlinOptions.freeCompilerArgs = listOf(
|
|
||||||
// "-include-binary", "${project.rootDir}/sodiumWrapper/static-arm32/lib/libsodium.a"
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
runningOnLinuxArm64 {
|
|
||||||
println("Configuring Linux Arm 64 targets")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
runningOnLinuxArm32 {
|
|
||||||
println("Configuring Linux Arm 32 targets")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
runningOnMacos {
|
|
||||||
println("Configuring macos targets")
|
|
||||||
iosX64() {
|
|
||||||
binaries {
|
|
||||||
framework {
|
|
||||||
optimized = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iosArm64() {
|
|
||||||
binaries {
|
|
||||||
framework {
|
|
||||||
optimized = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iosArm32() {
|
|
||||||
binaries {
|
|
||||||
framework {
|
|
||||||
optimized = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
macosX64() {
|
|
||||||
binaries {
|
|
||||||
framework {
|
|
||||||
optimized = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compilations.getByName("main") {
|
|
||||||
val libsodiumCinterop by cinterops.creating {
|
|
||||||
defFile(project.file("src/nativeInterop/cinterop/libsodium.def"))
|
|
||||||
compilerOpts.add("-I${project.rootDir}/sodiumWrapper/static-macos-x86-64/include")
|
|
||||||
}
|
|
||||||
kotlinOptions.freeCompilerArgs = listOf(
|
|
||||||
"-include-binary", "${project.rootDir}/sodiumWrapper/static-macos-x86-64/lib/libsodium.a"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tvosX64() {
|
|
||||||
binaries {
|
|
||||||
framework {
|
|
||||||
optimized = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tvosArm64() {
|
|
||||||
binaries {
|
|
||||||
framework {
|
|
||||||
optimized = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watchosArm64() {
|
|
||||||
binaries {
|
|
||||||
framework {
|
|
||||||
optimized = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watchosArm32() {
|
|
||||||
binaries {
|
|
||||||
framework {
|
|
||||||
optimized = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watchosX86() {
|
|
||||||
binaries {
|
|
||||||
framework {
|
|
||||||
optimized = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
runningOnWindows {
|
|
||||||
println("Configuring Mingw targets")
|
|
||||||
mingwX64() {
|
|
||||||
binaries {
|
|
||||||
staticLib {
|
|
||||||
optimized = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compilations.getByName("main") {
|
|
||||||
val libsodiumCinterop by cinterops.creating {
|
|
||||||
defFile(project.file("src/nativeInterop/cinterop/libsodium.def"))
|
|
||||||
compilerOpts.add("-I${project.rootDir}/sodiumWrapper/static-mingw-x86-64/include")
|
|
||||||
}
|
|
||||||
kotlinOptions.freeCompilerArgs = listOf(
|
|
||||||
"-include-binary", "${project.rootDir}/sodiumWrapper/static-mingw-x86-64/lib/libsodium.a"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println(targets.names)
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
val commonMain by getting {
|
|
||||||
dependencies {
|
|
||||||
implementation(kotlin(Deps.Common.stdLib))
|
|
||||||
implementation(kotlin(Deps.Common.test))
|
|
||||||
implementation(Deps.Common.kotlinBigNum)
|
|
||||||
api(project(Deps.Common.apiProject))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val commonTest by getting {
|
|
||||||
dependencies {
|
|
||||||
implementation(kotlin(Deps.Common.test))
|
|
||||||
implementation(kotlin(Deps.Common.testAnnotation))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val nativeDependencies = independentDependencyBlock {
|
|
||||||
}
|
|
||||||
|
|
||||||
val nativeMain by creating {
|
|
||||||
dependsOn(commonMain)
|
|
||||||
isRunningInIdea {
|
|
||||||
kotlin.setSrcDirs(emptySet<String>())
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
nativeDependencies(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val nativeTest by creating {
|
|
||||||
dependsOn(commonTest)
|
|
||||||
isRunningInIdea {
|
|
||||||
kotlin.setSrcDirs(emptySet<String>())
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Set up shared source sets
|
|
||||||
//linux, linuxArm32Hfp, linuxArm64
|
|
||||||
val linux64Bit = setOf(
|
|
||||||
"linuxX64"
|
|
||||||
)
|
|
||||||
val linuxArm64Bit = setOf(
|
|
||||||
"linuxArm64"
|
|
||||||
)
|
|
||||||
val linux32Bit = setOf(
|
|
||||||
"" // "linuxArm32Hfp"
|
|
||||||
)
|
|
||||||
|
|
||||||
//iosArm32, iosArm64, iosX64, macosX64, metadata, tvosArm64, tvosX64, watchosArm32, watchosArm64, watchosX86
|
|
||||||
val macos64Bit = setOf(
|
|
||||||
"macosX64"
|
|
||||||
)
|
|
||||||
val iosArm = setOf(
|
|
||||||
"iosArm64", "iosArm32"
|
|
||||||
)
|
|
||||||
val iosSimulator = setOf(
|
|
||||||
"iosX64"
|
|
||||||
)
|
|
||||||
val mingw64Bit = setOf(
|
|
||||||
"mingwX64"
|
|
||||||
)
|
|
||||||
|
|
||||||
val tvosArm = setOf(
|
|
||||||
"tvosArm64"
|
|
||||||
)
|
|
||||||
val tvosSimulator = setOf(
|
|
||||||
"tvosX64"
|
|
||||||
)
|
|
||||||
|
|
||||||
val watchosArm = setOf(
|
|
||||||
"watchosArm32", "watchosArm64"
|
|
||||||
)
|
|
||||||
val watchosSimulator = setOf(
|
|
||||||
"watchosX86"
|
|
||||||
)
|
|
||||||
|
|
||||||
targets.withType<KotlinNativeTarget> {
|
|
||||||
println("Target $name")
|
|
||||||
|
|
||||||
compilations.getByName("main") {
|
|
||||||
if (linux64Bit.contains(this@withType.name)) {
|
|
||||||
defaultSourceSet.dependsOn(nativeMain)
|
|
||||||
}
|
|
||||||
if (linuxArm64Bit.contains(this@withType.name)) {
|
|
||||||
defaultSourceSet.dependsOn(
|
|
||||||
createWorkaroundNativeMainSourceSet(
|
|
||||||
this@withType.name,
|
|
||||||
nativeDependencies
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
compilations.getByName("main") {
|
|
||||||
val libsodiumCinterop by cinterops.creating {
|
|
||||||
defFile(project.file("src/nativeInterop/cinterop/libsodium.def"))
|
|
||||||
compilerOpts.add("-I${project.rootDir}/sodiumWrapper/static-arm64/include/")
|
|
||||||
}
|
|
||||||
kotlinOptions.freeCompilerArgs = listOf(
|
|
||||||
"-include-binary", "${project.rootDir}/sodiumWrapper/static-arm64/lib/libsodium.a"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (linux32Bit.contains(this@withType.name)) {
|
|
||||||
defaultSourceSet.dependsOn(createWorkaroundNativeMainSourceSet(this@withType.name, nativeDependencies))
|
|
||||||
}
|
|
||||||
if (macos64Bit.contains(this@withType.name)) {
|
|
||||||
defaultSourceSet.dependsOn(createWorkaroundNativeMainSourceSet(this@withType.name, nativeDependencies))
|
|
||||||
}
|
|
||||||
//All ioses share the same static library
|
|
||||||
if (iosArm.contains(this@withType.name)) {
|
|
||||||
defaultSourceSet.dependsOn(createWorkaroundNativeMainSourceSet(this@withType.name, nativeDependencies))
|
|
||||||
println("Setting ios cinterop for $this")
|
|
||||||
val libsodiumCinterop by cinterops.creating {
|
|
||||||
defFile(project.file("src/nativeInterop/cinterop/libsodium.def"))
|
|
||||||
compilerOpts.add("-I${project.rootDir}/sodiumWrapper/static-ios/include")
|
|
||||||
}
|
|
||||||
kotlinOptions.freeCompilerArgs = listOf(
|
|
||||||
"-include-binary", "${project.rootDir}/sodiumWrapper/static-ios/lib/libsodium.a"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iosSimulator.contains(this@withType.name)) {
|
|
||||||
defaultSourceSet.dependsOn(createWorkaroundNativeMainSourceSet(this@withType.name, nativeDependencies))
|
|
||||||
println("Setting ios cinterop for $this")
|
|
||||||
val libsodiumCinterop by cinterops.creating {
|
|
||||||
defFile(project.file("src/nativeInterop/cinterop/libsodium.def"))
|
|
||||||
compilerOpts.add("-I${project.rootDir}/sodiumWrapper/static-ios-simulators/include")
|
|
||||||
}
|
|
||||||
kotlinOptions.freeCompilerArgs = listOf(
|
|
||||||
"-include-binary", "${project.rootDir}/sodiumWrapper/static-ios-simulators/lib/libsodium.a"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tvosArm.contains(this@withType.name)) {
|
|
||||||
defaultSourceSet.dependsOn(createWorkaroundNativeMainSourceSet(this@withType.name, nativeDependencies))
|
|
||||||
println("Setting ios cinterop for $this")
|
|
||||||
val libsodiumCinterop by cinterops.creating {
|
|
||||||
defFile(project.file("src/nativeInterop/cinterop/libsodium.def"))
|
|
||||||
compilerOpts.add("-I${project.rootDir}/sodiumWrapper/static-tvos/include")
|
|
||||||
}
|
|
||||||
kotlinOptions.freeCompilerArgs = listOf(
|
|
||||||
"-include-binary", "${project.rootDir}/sodiumWrapper/static-tvos/lib/libsodium.a"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tvosSimulator.contains(this@withType.name)) {
|
|
||||||
defaultSourceSet.dependsOn(createWorkaroundNativeMainSourceSet(this@withType.name, nativeDependencies))
|
|
||||||
println("Setting ios cinterop for $this")
|
|
||||||
val libsodiumCinterop by cinterops.creating {
|
|
||||||
defFile(project.file("src/nativeInterop/cinterop/libsodium.def"))
|
|
||||||
compilerOpts.add("-I${project.rootDir}/sodiumWrapper/static-tvos-simulators/include")
|
|
||||||
}
|
|
||||||
kotlinOptions.freeCompilerArgs = listOf(
|
|
||||||
"-include-binary", "${project.rootDir}/sodiumWrapper/static-tvos-simulators/lib/libsodium.a"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (watchosArm.contains(this@withType.name)) {
|
|
||||||
defaultSourceSet.dependsOn(createWorkaroundNativeMainSourceSet(this@withType.name, nativeDependencies))
|
|
||||||
println("Setting ios cinterop for $this")
|
|
||||||
val libsodiumCinterop by cinterops.creating {
|
|
||||||
defFile(project.file("src/nativeInterop/cinterop/libsodium.def"))
|
|
||||||
compilerOpts.add("-I${project.rootDir}/sodiumWrapper/static-watchos/include")
|
|
||||||
}
|
|
||||||
kotlinOptions.freeCompilerArgs = listOf(
|
|
||||||
"-include-binary", "${project.rootDir}/sodiumWrapper/static-watchos/lib/libsodium.a"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (watchosSimulator.contains(this@withType.name)) {
|
|
||||||
defaultSourceSet.dependsOn(createWorkaroundNativeMainSourceSet(this@withType.name, nativeDependencies))
|
|
||||||
println("Setting ios cinterop for $this")
|
|
||||||
val libsodiumCinterop by cinterops.creating {
|
|
||||||
defFile(project.file("src/nativeInterop/cinterop/libsodium.def"))
|
|
||||||
compilerOpts.add("-I${project.rootDir}/sodiumWrapper/static-watchos-simulators/include")
|
|
||||||
}
|
|
||||||
kotlinOptions.freeCompilerArgs = listOf(
|
|
||||||
"-include-binary", "${project.rootDir}/sodiumWrapper/static-watchos-simulators/lib/libsodium.a"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
compilations.getByName("test") {
|
|
||||||
println("Setting native test dep for $this@withType.name")
|
|
||||||
defaultSourceSet.dependsOn(nativeTest)
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
runningOnLinuxx86_64 {
|
|
||||||
println("Configuring Linux 64 Bit source sets")
|
|
||||||
val jvmMain by getting {
|
|
||||||
dependencies {
|
|
||||||
implementation(kotlin(Deps.Jvm.stdLib))
|
|
||||||
implementation(kotlin(Deps.Jvm.test))
|
|
||||||
implementation(kotlin(Deps.Jvm.testJUnit))
|
|
||||||
|
|
||||||
//lazysodium
|
|
||||||
implementation(Deps.Jvm.Delegated.lazysodium)
|
|
||||||
implementation(Deps.Jvm.Delegated.jna)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val jvmTest by getting {
|
|
||||||
dependencies {
|
|
||||||
implementation(kotlin(Deps.Jvm.test))
|
|
||||||
implementation(kotlin(Deps.Jvm.testJUnit))
|
|
||||||
implementation(kotlin(Deps.Jvm.reflection))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val jsMain by getting {
|
|
||||||
dependencies {
|
|
||||||
implementation(kotlin(Deps.Js.stdLib))
|
|
||||||
implementation(npm(Deps.Js.Npm.libsodiumWrappers.first, Deps.Js.Npm.libsodiumWrappers.second))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val jsTest by getting {
|
|
||||||
dependencies {
|
|
||||||
implementation(kotlin(Deps.Js.test))
|
|
||||||
implementation(npm(Deps.Js.Npm.libsodiumWrappers.first, Deps.Js.Npm.libsodiumWrappers.second))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val linuxX64Main by getting {
|
|
||||||
isRunningInIdea {
|
|
||||||
kotlin.srcDir("src/nativeMain/kotlin")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val linuxX64Test by getting {
|
|
||||||
dependsOn(nativeTest)
|
|
||||||
isRunningInIdea {
|
|
||||||
kotlin.srcDir("src/nativeTest/kotlin")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
runningOnMacos {
|
|
||||||
println("Configuring Macos source sets")
|
|
||||||
val macosX64Main by getting {
|
|
||||||
dependsOn(nativeMain)
|
|
||||||
if (ideaActive) {
|
|
||||||
kotlin.srcDir("src/nativeMain/kotlin")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
val macosX64Test by getting {
|
|
||||||
dependsOn(nativeTest)
|
|
||||||
if (ideaActive) {
|
|
||||||
kotlin.srcDir("src/nativeTest/kotlin")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
val tvosX64Main by getting {
|
|
||||||
dependsOn(commonMain)
|
|
||||||
}
|
|
||||||
|
|
||||||
val tvosArm64Main by getting {
|
|
||||||
dependsOn(commonMain)
|
|
||||||
}
|
|
||||||
|
|
||||||
val watchosX86Main by getting {
|
|
||||||
dependsOn(commonMain)
|
|
||||||
}
|
|
||||||
|
|
||||||
val watchosArm64Main by getting {
|
|
||||||
dependsOn(commonMain)
|
|
||||||
}
|
|
||||||
|
|
||||||
val watchosArm32Main by getting {
|
|
||||||
dependsOn(commonMain)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (hostOsName == "windows") {
|
|
||||||
val mingwX64Main by getting {
|
|
||||||
dependsOn(nativeMain)
|
|
||||||
if (ideaActive) {
|
|
||||||
kotlin.srcDir("src/nativeMain/kotlin")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val mingwX64Test by getting {
|
|
||||||
dependsOn(nativeTest)
|
|
||||||
if (ideaActive) {
|
|
||||||
kotlin.srcDir("src/nativeTest/kotlin")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
all {
|
|
||||||
languageSettings.enableLanguageFeature("InlineClasses")
|
|
||||||
languageSettings.useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
|
|
||||||
languageSettings.useExperimentalAnnotation("kotlin.ExperimentalStdlibApi")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tasks {
|
|
||||||
|
|
||||||
|
|
||||||
create<Jar>("javadocJar") {
|
|
||||||
dependsOn(dokkaJavadoc)
|
|
||||||
archiveClassifier.set("javadoc")
|
|
||||||
from(dokkaJavadoc.get().outputDirectory)
|
|
||||||
}
|
|
||||||
|
|
||||||
dokkaJavadoc {
|
|
||||||
println("Dokka !")
|
|
||||||
dokkaSourceSets {
|
|
||||||
create("commonMain") {
|
|
||||||
displayName = "common"
|
|
||||||
platform = "common"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (getHostOsName() == "linux" && getHostArchitecture() == "x86-64") {
|
|
||||||
val jvmTest by getting(Test::class) {
|
|
||||||
testLogging {
|
|
||||||
events("PASSED", "FAILED", "SKIPPED")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val linuxX64Test by getting(KotlinNativeTest::class) {
|
|
||||||
|
|
||||||
testLogging {
|
|
||||||
events("PASSED", "FAILED", "SKIPPED")
|
|
||||||
showStandardStreams = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val jsNodeTest by getting(KotlinJsTest::class) {
|
|
||||||
testLogging {
|
|
||||||
events("PASSED", "FAILED", "SKIPPED")
|
|
||||||
// showStandardStreams = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// val legacyjsNodeTest by getting(KotlinJsTest::class) {
|
|
||||||
//
|
|
||||||
// testLogging {
|
|
||||||
// events("PASSED", "FAILED", "SKIPPED")
|
|
||||||
// showStandardStreams = true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// val jsIrBrowserTest by getting(KotlinJsTest::class) {
|
|
||||||
// testLogging {
|
|
||||||
// events("PASSED", "FAILED", "SKIPPED")
|
|
||||||
// showStandardStreams = true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getHostOsName() == "windows") {
|
|
||||||
val mingwX64Test by getting(KotlinNativeTest::class) {
|
|
||||||
|
|
||||||
testLogging {
|
|
||||||
events("PASSED", "FAILED", "SKIPPED")
|
|
||||||
showStandardStreams = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
signing {
|
|
||||||
isRequired = false
|
|
||||||
sign(publishing.publications)
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications.withType(MavenPublication::class) {
|
|
||||||
artifact(tasks["javadocJar"])
|
|
||||||
pom {
|
|
||||||
name.set("Kotlin Multiplatform Crypto")
|
|
||||||
description.set("Kotlin Multiplatform Crypto library")
|
|
||||||
url.set("https://github.com/ionspin/kotlin-multiplatform-crypto")
|
|
||||||
licenses {
|
|
||||||
license {
|
|
||||||
name.set("The Apache License, Version 2.0")
|
|
||||||
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
developers {
|
|
||||||
developer {
|
|
||||||
id.set("ionspin")
|
|
||||||
name.set("Ugljesa Jovanovic")
|
|
||||||
email.set("opensource@ionspin.com")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scm {
|
|
||||||
url.set("https://github.com/ionspin/kotlin-multiplatform-crypto")
|
|
||||||
connection.set("scm:git:git://git@github.com:ionspin/kotlin-multiplatform-crypto.git")
|
|
||||||
developerConnection.set("scm:git:ssh://git@github.com:ionspin/kotlin-multiplatform-crypto.git")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
|
|
||||||
url = uri(sonatypeStaging)
|
|
||||||
credentials {
|
|
||||||
username = sonatypeUsername ?: sonatypeUsernameEnv ?: ""
|
|
||||||
password = sonatypePassword ?: sonatypePasswordEnv ?: ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
maven {
|
|
||||||
name = "snapshot"
|
|
||||||
url = uri(sonatypeSnapshots)
|
|
||||||
credentials {
|
|
||||||
username = sonatypeUsername ?: sonatypeUsernameEnv ?: ""
|
|
||||||
password = sonatypePassword ?: sonatypePasswordEnv ?: ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//configurations.forEach {
|
|
||||||
//
|
|
||||||
// if (it.name == "linuxCompileKlibraries") {
|
|
||||||
// println("Configuration name: ${it.name}")
|
|
||||||
// it.attributes {
|
|
||||||
// this.keySet().forEach { key ->
|
|
||||||
// val attribute = getAttribute(key)
|
|
||||||
// println(" |-- Attribute $key ${attribute}")
|
|
||||||
// attribute(org.jetbrains.kotlin.gradle.plugin.ProjectLocalConfigurations.ATTRIBUTE, "publicZ")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 20-Jul-2019
|
|
||||||
*/
|
|
||||||
object Config {
|
|
||||||
const val DEBUG = false
|
|
||||||
}
|
|
@ -1,216 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.authenticated.XChaCha20Poly1305Delegated
|
|
||||||
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bProperties
|
|
||||||
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bDelegated
|
|
||||||
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bDelegatedStateless
|
|
||||||
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bMultipart
|
|
||||||
import com.ionspin.kotlin.crypto.hash.sha.*
|
|
||||||
import com.ionspin.kotlin.crypto.keyderivation.ArgonResult
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 24-May-2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
object CryptoInitializerDelegated : CryptoInitializer {
|
|
||||||
override suspend fun initialize() {
|
|
||||||
Initializer.initialize()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun initializeWithCallback(done: () -> Unit) {
|
|
||||||
Initializer.initializeWithCallback(done)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isInitialized(): Boolean {
|
|
||||||
return Initializer.isInitialized()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object CryptoPrimitives : PrimitivesApi {
|
|
||||||
|
|
||||||
object Blake2b {
|
|
||||||
fun updateable(key: UByteArray? = null, hashLength: Int = Blake2bProperties.MAX_HASH_BYTES): com.ionspin.kotlin.crypto.hash.blake2b.Blake2bMultipart {
|
|
||||||
checkInitialization()
|
|
||||||
return Blake2bDelegated(key, hashLength)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stateless(message: UByteArray, key: UByteArray = ubyteArrayOf(), hashLength: Int = Blake2bProperties.MAX_HASH_BYTES): UByteArray {
|
|
||||||
checkInitialization()
|
|
||||||
return Blake2bDelegatedStateless.digest(message, key, hashLength)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object Sha256 {
|
|
||||||
fun updateable(): com.ionspin.kotlin.crypto.hash.sha.Sha256 {
|
|
||||||
checkInitialization()
|
|
||||||
return Sha256Delegated()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stateless(message: UByteArray) : UByteArray{
|
|
||||||
checkInitialization()
|
|
||||||
return Sha256StatelessDelegated.digest(inputMessage = message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object Sha512 {
|
|
||||||
fun updateable(): Sha512Multipart {
|
|
||||||
checkInitialization()
|
|
||||||
return Sha512Delegated()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stateless(message: UByteArray) : UByteArray {
|
|
||||||
checkInitialization()
|
|
||||||
return Sha512StatelessDelegated.digest(inputMessage = message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkInitialization() {
|
|
||||||
if (!Initializer.isInitialized()) {
|
|
||||||
throw RuntimeException("Platform library not initialized, check if you called Initializer.initialize()")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashBlake2bMultipart(key: UByteArray?, hashLength: Int): Blake2bMultipart {
|
|
||||||
checkInitialization()
|
|
||||||
return Blake2bDelegated(key, hashLength)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashBlake2b(message: UByteArray, key: UByteArray, hashLength: Int): UByteArray {
|
|
||||||
checkInitialization()
|
|
||||||
return Blake2bDelegatedStateless.digest(message, key, hashLength)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashSha256Multipart(): com.ionspin.kotlin.crypto.hash.sha.Sha256 {
|
|
||||||
checkInitialization()
|
|
||||||
return Sha256Delegated()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashSha256(message: UByteArray): UByteArray {
|
|
||||||
checkInitialization()
|
|
||||||
return Sha256StatelessDelegated.digest(inputMessage = message)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashSha512Multipart(): com.ionspin.kotlin.crypto.hash.sha.Sha512Multipart {
|
|
||||||
checkInitialization()
|
|
||||||
return Sha512Delegated()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashSha512(message: UByteArray): UByteArray {
|
|
||||||
checkInitialization()
|
|
||||||
return Sha512StatelessDelegated.digest(inputMessage = message)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deriveKey(
|
|
||||||
password: String,
|
|
||||||
salt: String?,
|
|
||||||
key: String,
|
|
||||||
associatedData: String,
|
|
||||||
parallelism: Int,
|
|
||||||
tagLength: Int,
|
|
||||||
memory: Int,
|
|
||||||
numberOfIterations: Int
|
|
||||||
): ArgonResult {
|
|
||||||
// return Argon2Delegated.derive(
|
|
||||||
// password,
|
|
||||||
// salt,
|
|
||||||
// key,
|
|
||||||
// associatedData,
|
|
||||||
// parallelism
|
|
||||||
// tagLength,
|
|
||||||
// memory,
|
|
||||||
// numberOfIterations
|
|
||||||
// )
|
|
||||||
TODO()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun SymmetricKey.Companion.randomKey() : SymmetricKey {
|
|
||||||
return SymmetricKey(SRNG.getRandomBytes(32))
|
|
||||||
}
|
|
||||||
|
|
||||||
object Crypto {
|
|
||||||
|
|
||||||
object Hash : HashApi {
|
|
||||||
override fun hash(data: UByteArray, key : UByteArray) : HashedData {
|
|
||||||
return HashedData(Blake2bDelegatedStateless.digest(data, key))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun multipartHash(key: UByteArray?) : com.ionspin.kotlin.crypto.hash.MultipartHash {
|
|
||||||
return Blake2bDelegated(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object Encryption : EncryptionApi {
|
|
||||||
override fun encrypt(key: SymmetricKey, data : Encryptable<*>, associatedData : UByteArray) : EncryptedData {
|
|
||||||
if (key.value.size != 32) {
|
|
||||||
throw RuntimeException("Invalid key size! Required 32, supplied ${key.value.size}")
|
|
||||||
}
|
|
||||||
val nonce = SRNG.getRandomBytes(24)
|
|
||||||
return EncryptedData(XChaCha20Poly1305Delegated.encrypt(key.value, nonce, data.toEncryptableForm(), associatedData), nonce)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <T: Encryptable<T>> decrypt(key: SymmetricKey, encryptedData : EncryptedData, associatedData: UByteArray, byteArrayDeserializer : (UByteArray) -> T) : T {
|
|
||||||
return byteArrayDeserializer(XChaCha20Poly1305Delegated.decrypt(key.value, encryptedData.nonce, encryptedData.ciphertext, associatedData))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createMultipartEncryptor(key: SymmetricKey): MultipartAuthenticatedEncryption {
|
|
||||||
return MultipartAuthenticatedEncryptor(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createMultipartDecryptor(key: SymmetricKey, header: MultipartEncryptionHeader) : MultipartAuthenticatedDecryption {
|
|
||||||
val decryptor = XChaCha20Poly1305Delegated()
|
|
||||||
decryptor.initializeForDecryption(key.value, header.nonce)
|
|
||||||
return MultipartAuthenticatedDecryptor(decryptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MultipartAuthenticatedEncryptor internal constructor(val key : SymmetricKey) : MultipartAuthenticatedEncryption {
|
|
||||||
|
|
||||||
val header : MultipartEncryptionHeader
|
|
||||||
val primitive = XChaCha20Poly1305Delegated()
|
|
||||||
init {
|
|
||||||
header = MultipartEncryptionHeader(primitive.initializeForEncryption(key.value))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun startEncryption(): MultipartEncryptionHeader {
|
|
||||||
return header
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun encryptPartialData(data: UByteArray, associatedData: UByteArray): EncryptedDataPart {
|
|
||||||
return EncryptedDataPart(primitive.encrypt(data, associatedData))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cleanup() {
|
|
||||||
primitive.cleanup()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class MultipartAuthenticatedDecryptor internal constructor(val decryptor: XChaCha20Poly1305Delegated) : MultipartAuthenticatedDecryption {
|
|
||||||
override fun decryptPartialData(data: EncryptedDataPart, associatedData: UByteArray): DecryptedDataPart {
|
|
||||||
return DecryptedDataPart(decryptor.decrypt(data.data, associatedData))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cleanup() {
|
|
||||||
decryptor.cleanup()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
expect object Initializer {
|
|
||||||
fun isInitialized() : Boolean
|
|
||||||
|
|
||||||
suspend fun initialize()
|
|
||||||
|
|
||||||
fun initializeWithCallback(done: () -> (Unit))
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
|||||||
package _multiplatform_crypto_delegated
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 24-May-2020
|
|
||||||
*/
|
|
||||||
//Workaround for https://youtrack.jetbrains.com/issue/KT-36878
|
|
||||||
val byteArray = byteArrayOf(0)
|
|
||||||
val byte = 0.toByte()
|
|
||||||
val longArray = longArrayOf(0)
|
|
||||||
val long = 0L
|
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 21-Sep-2019
|
|
||||||
*/
|
|
||||||
expect object SRNG {
|
|
||||||
fun getRandomBytes(amount : Int) : UByteArray
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.authenticated
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 14-Jun-2020
|
|
||||||
*/
|
|
||||||
expect class XChaCha20Poly1305Delegated internal constructor() {
|
|
||||||
internal constructor(key: UByteArray, testState : UByteArray, testHeader: UByteArray, isDecryptor: Boolean)
|
|
||||||
companion object {
|
|
||||||
fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, associatedData: UByteArray) : UByteArray
|
|
||||||
fun decrypt(key: UByteArray, nonce: UByteArray, ciphertext: UByteArray, associatedData: UByteArray) : UByteArray
|
|
||||||
}
|
|
||||||
fun initializeForEncryption(key: UByteArray) : UByteArray
|
|
||||||
fun initializeForDecryption(key: UByteArray, header: UByteArray)
|
|
||||||
fun encrypt(data: UByteArray, associatedData: UByteArray = ubyteArrayOf()) : UByteArray
|
|
||||||
fun decrypt(data: UByteArray, associatedData: UByteArray = ubyteArrayOf()) : UByteArray
|
|
||||||
fun cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto.hash.blake2b
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 14-Jul-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
expect class Blake2bDelegated(key: UByteArray? = null, hashLength: Int = Blake2bProperties.MAX_HASH_BYTES) : Blake2bMultipart
|
|
||||||
|
|
||||||
|
|
||||||
expect object Blake2bDelegatedStateless : Blake2b
|
|
||||||
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto.hash.sha
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 17-Jul-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
expect class Sha256Delegated() : Sha256
|
|
||||||
|
|
||||||
expect object Sha256StatelessDelegated : StatelessSha256
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto.hash.sha
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 17-Jul-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
expect class Sha512Delegated() : Sha512Multipart
|
|
||||||
|
|
||||||
expect object Sha512StatelessDelegated : Sha512
|
|
@ -1,10 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.keyderivation.argon2
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.keyderivation.KeyDerivationFunction
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 24-May-2020
|
|
||||||
*/
|
|
||||||
interface Argon2 : KeyDerivationFunction
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto.parallelization
|
|
||||||
|
|
||||||
import kotlin.time.ExperimentalTime
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 17-May-2020
|
|
||||||
*/
|
|
||||||
@ExperimentalTime
|
|
||||||
object Coroutines14 {
|
|
||||||
fun argonParallel() : Array<UByte> {
|
|
||||||
// val argon = Argon2()
|
|
||||||
// argon
|
|
||||||
println("Placeholder")
|
|
||||||
return emptyArray()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,216 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:Suppress("EXPERIMENTAL_API_USAGE")
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto.util
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 15-Jul-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
inline fun <reified T> Array<T>.chunked(sliceSize: Int): Array<Array<T>> {
|
|
||||||
val last = this.size % sliceSize
|
|
||||||
val hasLast = last != 0
|
|
||||||
val numberOfSlices = this.size / sliceSize
|
|
||||||
|
|
||||||
|
|
||||||
val result : MutableList<List<T>> = MutableList<List<T>>(0) { emptyList() }
|
|
||||||
|
|
||||||
for (i in 0 until numberOfSlices) {
|
|
||||||
result.add(this.slice(i * sliceSize until (i + 1) * sliceSize))
|
|
||||||
}
|
|
||||||
if (hasLast) {
|
|
||||||
result.add(this.slice(numberOfSlices * sliceSize until this.size))
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.map { it.toTypedArray() }.toTypedArray()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
infix fun UInt.rotateRight(places: Int): UInt {
|
|
||||||
return (this shr places) xor (this shl (32 - places))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
infix fun ULong.rotateRight(places: Int): ULong {
|
|
||||||
return (this shr places) xor (this shl (64 - places))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
infix fun Array<UByte>.xor(other : Array<UByte>) : Array<UByte> {
|
|
||||||
if (this.size != other.size) {
|
|
||||||
throw RuntimeException("Operands of different sizes are not supported yet")
|
|
||||||
}
|
|
||||||
return Array(this.size) { this[it] xor other[it] }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
infix fun UByteArray.xor(other : UByteArray) : UByteArray {
|
|
||||||
if (this.size != other.size) {
|
|
||||||
throw RuntimeException("Operands of different sizes are not supported yet")
|
|
||||||
}
|
|
||||||
return UByteArray(this.size) { this[it] xor other[it] }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// UInt / Array utils
|
|
||||||
|
|
||||||
fun UInt.toBigEndianUByteArray() : Array<UByte> {
|
|
||||||
return Array<UByte> (4) {
|
|
||||||
((this shr (24 - (it * 8))) and 0xFFU).toUByte()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun UInt.toLittleEndianTypedUByteArray() : Array<UByte> {
|
|
||||||
return Array<UByte> (4) {
|
|
||||||
((this shr (it * 8)) and 0xFFU).toUByte()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun UInt.toLittleEndianUByteArray() : UByteArray {
|
|
||||||
return UByteArray (4) {
|
|
||||||
((this shr (it * 8)) and 0xFFU).toUByte()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UInt / Array utils
|
|
||||||
|
|
||||||
fun ULong.toBigEndianUByteArray() : Array<UByte> {
|
|
||||||
return Array<UByte> (8) {
|
|
||||||
((this shr (56 - (it * 8))) and 0xFFU).toUByte()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ULong.toLittleEndianTypedUByteArray() : Array<UByte> {
|
|
||||||
return Array<UByte> (8) {
|
|
||||||
((this shr (it * 8)) and 0xFFU).toUByte()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun ULong.toLittleEndianUByteArray() :UByteArray {
|
|
||||||
return UByteArray (8) {
|
|
||||||
((this shr (it * 8)) and 0xFFU).toUByte()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun Array<UByte>.fromLittleEndianArrayToULong() : ULong {
|
|
||||||
if (this.size > 8) {
|
|
||||||
throw RuntimeException("ore than 8 bytes in input, potential overflow")
|
|
||||||
}
|
|
||||||
var ulong = this.foldIndexed(0UL) { index, acc, uByte -> acc or (uByte.toULong() shl (index * 8))}
|
|
||||||
return ulong
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun UByteArray.fromLittleEndianArrayToULong() : ULong {
|
|
||||||
if (this.size > 8) {
|
|
||||||
throw RuntimeException("ore than 8 bytes in input, potential overflow")
|
|
||||||
}
|
|
||||||
var ulong = this.foldIndexed(0UL) { index, acc, uByte -> acc or (uByte.toULong() shl (index * 8))}
|
|
||||||
return ulong
|
|
||||||
}
|
|
||||||
|
|
||||||
fun UByteArray.arrayChunked(sliceSize: Int): List<UByteArray> {
|
|
||||||
val last = this.size % sliceSize
|
|
||||||
val hasLast = last != 0
|
|
||||||
val numberOfSlices = this.size / sliceSize
|
|
||||||
|
|
||||||
|
|
||||||
val result : MutableList<UByteArray> = MutableList<UByteArray>(0) { ubyteArrayOf() }
|
|
||||||
|
|
||||||
for (i in 0 until numberOfSlices) {
|
|
||||||
result.add(this.sliceArray(i * sliceSize until (i + 1) * sliceSize))
|
|
||||||
}
|
|
||||||
if (hasLast) {
|
|
||||||
result.add(this.sliceArray(numberOfSlices * sliceSize until this.size))
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun Array<UByte>.fromBigEndianArrayToULong() : ULong {
|
|
||||||
if (this.size > 8) {
|
|
||||||
throw RuntimeException("ore than 8 bytes in input, potential overflow")
|
|
||||||
}
|
|
||||||
var ulong = this.foldIndexed(0UL) {
|
|
||||||
index, acc, uByte ->
|
|
||||||
val res = acc or (uByte.toULong() shl (56 - (index * 8)))
|
|
||||||
res
|
|
||||||
|
|
||||||
}
|
|
||||||
return ulong
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun Array<UByte>.fromLittleEndianArrayToUInt() : UInt {
|
|
||||||
if (this.size > 4) {
|
|
||||||
throw RuntimeException("ore than 8 bytes in input, potential overflow")
|
|
||||||
}
|
|
||||||
var uint = this.foldIndexed(0U) { index, acc, uByte -> acc or (uByte.toUInt() shl (index * 8))}
|
|
||||||
return uint
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun UByteArray.fromLittleEndianArrayToUInt() : UInt {
|
|
||||||
if (this.size > 4) {
|
|
||||||
throw RuntimeException("ore than 8 bytes in input, potential overflow")
|
|
||||||
}
|
|
||||||
var uint = this.foldIndexed(0U) { index, acc, uByte -> acc or (uByte.toUInt() shl (index * 8))}
|
|
||||||
return uint
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun Array<UByte>.fromBigEndianArrayToUInt() : UInt {
|
|
||||||
if (this.size > 4) {
|
|
||||||
throw RuntimeException("ore than 8 bytes in input, potential overflow")
|
|
||||||
}
|
|
||||||
var uint = this.foldIndexed(0U) { index, acc, uByte -> acc or (uByte.toUInt() shl (24 - (index * 8))) }
|
|
||||||
return uint
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
operator fun UInt.plus(other : UByteArray) : UByteArray {
|
|
||||||
return this.toLittleEndianUByteArray() + other
|
|
||||||
}
|
|
||||||
|
|
||||||
//AES Flatten
|
|
||||||
fun Collection<UByteArray>.flattenToUByteArray(): UByteArray {
|
|
||||||
val result = UByteArray(sumBy { it.size })
|
|
||||||
var position = 0
|
|
||||||
for (element in this) {
|
|
||||||
element.forEach { uByte ->
|
|
||||||
result[position] = uByte
|
|
||||||
position++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import kotlin.test.Test
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 17-Jul-2020
|
|
||||||
*/
|
|
||||||
class DebugTest {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.util.testBlocking
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 21-Sep-2019
|
|
||||||
*/
|
|
||||||
class SRNGTest {
|
|
||||||
@Test
|
|
||||||
fun testSrng() = testBlocking {
|
|
||||||
CryptoInitializerDelegated.initialize()
|
|
||||||
//Just a sanity test, need to add better srng tests.
|
|
||||||
val randomBytes1 = SRNG.getRandomBytes(10)
|
|
||||||
val randomBytes2 = SRNG.getRandomBytes(10)
|
|
||||||
assertTrue { !randomBytes1.contentEquals(randomBytes2) }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,240 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.authenticated
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.CryptoInitializerDelegated
|
|
||||||
import com.ionspin.kotlin.crypto.Initializer
|
|
||||||
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
|
||||||
import com.ionspin.kotlin.crypto.util.hexColumsPrint
|
|
||||||
import com.ionspin.kotlin.crypto.util.testBlocking
|
|
||||||
import kotlin.test.Ignore
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertFails
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 17-Jun-2020
|
|
||||||
*/
|
|
||||||
class XChaCha20Poly1305Test {
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun xChaCha20Poly1305() = testBlocking {
|
|
||||||
CryptoInitializerDelegated.initialize()
|
|
||||||
|
|
||||||
assertTrue {
|
|
||||||
val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " +
|
|
||||||
"only one tip for the future, sunscreen would be it.").encodeToUByteArray()
|
|
||||||
|
|
||||||
val associatedData = ubyteArrayOf(
|
|
||||||
0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U
|
|
||||||
)
|
|
||||||
val key = ubyteArrayOf(
|
|
||||||
0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
|
|
||||||
0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU,
|
|
||||||
0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
|
|
||||||
0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU,
|
|
||||||
)
|
|
||||||
|
|
||||||
val nonce = ubyteArrayOf(
|
|
||||||
0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
|
|
||||||
0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU,
|
|
||||||
0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
|
|
||||||
)
|
|
||||||
|
|
||||||
val expected = ubyteArrayOf(
|
|
||||||
0xbdU, 0x6dU, 0x17U, 0x9dU, 0x3eU, 0x83U, 0xd4U, 0x3bU,
|
|
||||||
0x95U, 0x76U, 0x57U, 0x94U, 0x93U, 0xc0U, 0xe9U, 0x39U,
|
|
||||||
0x57U, 0x2aU, 0x17U, 0x00U, 0x25U, 0x2bU, 0xfaU, 0xccU,
|
|
||||||
0xbeU, 0xd2U, 0x90U, 0x2cU, 0x21U, 0x39U, 0x6cU, 0xbbU,
|
|
||||||
0x73U, 0x1cU, 0x7fU, 0x1bU, 0x0bU, 0x4aU, 0xa6U, 0x44U,
|
|
||||||
0x0bU, 0xf3U, 0xa8U, 0x2fU, 0x4eU, 0xdaU, 0x7eU, 0x39U,
|
|
||||||
0xaeU, 0x64U, 0xc6U, 0x70U, 0x8cU, 0x54U, 0xc2U, 0x16U,
|
|
||||||
0xcbU, 0x96U, 0xb7U, 0x2eU, 0x12U, 0x13U, 0xb4U, 0x52U,
|
|
||||||
0x2fU, 0x8cU, 0x9bU, 0xa4U, 0x0dU, 0xb5U, 0xd9U, 0x45U,
|
|
||||||
0xb1U, 0x1bU, 0x69U, 0xb9U, 0x82U, 0xc1U, 0xbbU, 0x9eU,
|
|
||||||
0x3fU, 0x3fU, 0xacU, 0x2bU, 0xc3U, 0x69U, 0x48U, 0x8fU,
|
|
||||||
0x76U, 0xb2U, 0x38U, 0x35U, 0x65U, 0xd3U, 0xffU, 0xf9U,
|
|
||||||
0x21U, 0xf9U, 0x66U, 0x4cU, 0x97U, 0x63U, 0x7dU, 0xa9U,
|
|
||||||
0x76U, 0x88U, 0x12U, 0xf6U, 0x15U, 0xc6U, 0x8bU, 0x13U,
|
|
||||||
0xb5U, 0x2eU, 0xc0U, 0x87U, 0x59U, 0x24U, 0xc1U, 0xc7U,
|
|
||||||
0x98U, 0x79U, 0x47U, 0xdeU, 0xafU, 0xd8U, 0x78U, 0x0aU,
|
|
||||||
0xcfU, 0x49U
|
|
||||||
)
|
|
||||||
val encrypted = XChaCha20Poly1305Delegated.encrypt(key, nonce, message, associatedData)
|
|
||||||
encrypted.hexColumsPrint()
|
|
||||||
val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, associatedData)
|
|
||||||
println("Decrypted")
|
|
||||||
decrypted.hexColumsPrint()
|
|
||||||
println("----------")
|
|
||||||
encrypted.contentEquals(expected) && decrypted.contentEquals(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue {
|
|
||||||
val message = ubyteArrayOf(
|
|
||||||
0x00U
|
|
||||||
)
|
|
||||||
val associatedData = ubyteArrayOf(
|
|
||||||
0x00U
|
|
||||||
)
|
|
||||||
val key = ubyteArrayOf(
|
|
||||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
|
||||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
|
||||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
|
||||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
|
||||||
)
|
|
||||||
|
|
||||||
val nonce = ubyteArrayOf(
|
|
||||||
0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U, 0x09U, 0x0aU, 0x0bU,
|
|
||||||
0x0cU, 0x0dU, 0x0eU, 0x0fU, 0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
|
|
||||||
)
|
|
||||||
|
|
||||||
val expected = ubyteArrayOf(
|
|
||||||
0xbdU, 0x3bU, 0x8aU, 0xd7U, 0xa1U, 0x9dU, 0xe8U, 0xc4U, 0x55U,
|
|
||||||
0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU
|
|
||||||
)
|
|
||||||
val encrypted = XChaCha20Poly1305Delegated.encrypt(key, nonce, message, associatedData)
|
|
||||||
val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, associatedData)
|
|
||||||
|
|
||||||
encrypted.contentEquals(expected) && decrypted.contentEquals(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore() //"Will fail because nonce is not a parameter any more"
|
|
||||||
@Test
|
|
||||||
fun updateableXChaCha20Poly1305() {
|
|
||||||
assertTrue {
|
|
||||||
val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " +
|
|
||||||
"only one tip for the future, sunscreen would be it.").encodeToUByteArray()
|
|
||||||
|
|
||||||
val associatedData = ubyteArrayOf(
|
|
||||||
0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U
|
|
||||||
)
|
|
||||||
val key = ubyteArrayOf(
|
|
||||||
0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
|
|
||||||
0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU,
|
|
||||||
0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
|
|
||||||
0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU,
|
|
||||||
)
|
|
||||||
|
|
||||||
val nonce = ubyteArrayOf(
|
|
||||||
0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
|
|
||||||
0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU,
|
|
||||||
0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
|
|
||||||
)
|
|
||||||
|
|
||||||
val expected = ubyteArrayOf(
|
|
||||||
0xbdU, 0x6dU, 0x17U, 0x9dU, 0x3eU, 0x83U, 0xd4U, 0x3bU,
|
|
||||||
0x95U, 0x76U, 0x57U, 0x94U, 0x93U, 0xc0U, 0xe9U, 0x39U,
|
|
||||||
0x57U, 0x2aU, 0x17U, 0x00U, 0x25U, 0x2bU, 0xfaU, 0xccU,
|
|
||||||
0xbeU, 0xd2U, 0x90U, 0x2cU, 0x21U, 0x39U, 0x6cU, 0xbbU,
|
|
||||||
0x73U, 0x1cU, 0x7fU, 0x1bU, 0x0bU, 0x4aU, 0xa6U, 0x44U,
|
|
||||||
0x0bU, 0xf3U, 0xa8U, 0x2fU, 0x4eU, 0xdaU, 0x7eU, 0x39U,
|
|
||||||
0xaeU, 0x64U, 0xc6U, 0x70U, 0x8cU, 0x54U, 0xc2U, 0x16U,
|
|
||||||
0xcbU, 0x96U, 0xb7U, 0x2eU, 0x12U, 0x13U, 0xb4U, 0x52U,
|
|
||||||
0x2fU, 0x8cU, 0x9bU, 0xa4U, 0x0dU, 0xb5U, 0xd9U, 0x45U,
|
|
||||||
0xb1U, 0x1bU, 0x69U, 0xb9U, 0x82U, 0xc1U, 0xbbU, 0x9eU,
|
|
||||||
0x3fU, 0x3fU, 0xacU, 0x2bU, 0xc3U, 0x69U, 0x48U, 0x8fU,
|
|
||||||
0x76U, 0xb2U, 0x38U, 0x35U, 0x65U, 0xd3U, 0xffU, 0xf9U,
|
|
||||||
0x21U, 0xf9U, 0x66U, 0x4cU, 0x97U, 0x63U, 0x7dU, 0xa9U,
|
|
||||||
0x76U, 0x88U, 0x12U, 0xf6U, 0x15U, 0xc6U, 0x8bU, 0x13U,
|
|
||||||
0xb5U, 0x2eU, 0xc0U, 0x87U, 0x59U, 0x24U, 0xc1U, 0xc7U,
|
|
||||||
0x98U, 0x79U, 0x47U, 0xdeU, 0xafU, 0xd8U, 0x78U, 0x0aU,
|
|
||||||
0xcfU, 0x49U
|
|
||||||
)
|
|
||||||
// val xChaChaPoly = XChaCha20Poly1305Delegated(key, associatedData)
|
|
||||||
// val firstChunk = xChaChaPoly.encrypt(message)
|
|
||||||
// val finalChunk = xChaChaPoly.finishEncryption().first
|
|
||||||
// val result = firstChunk + finalChunk
|
|
||||||
|
|
||||||
// result.contentEquals(expected)
|
|
||||||
1 == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue {
|
|
||||||
val message = ubyteArrayOf(
|
|
||||||
0x00U
|
|
||||||
)
|
|
||||||
val associatedData = ubyteArrayOf(
|
|
||||||
0x00U
|
|
||||||
)
|
|
||||||
val key = ubyteArrayOf(
|
|
||||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
|
||||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
|
||||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
|
||||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
|
||||||
)
|
|
||||||
|
|
||||||
val nonce = ubyteArrayOf(
|
|
||||||
0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U, 0x09U, 0x0aU, 0x0bU,
|
|
||||||
0x0cU, 0x0dU, 0x0eU, 0x0fU, 0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U,
|
|
||||||
)
|
|
||||||
|
|
||||||
val expected = ubyteArrayOf(
|
|
||||||
0xbdU, 0x3bU, 0x8aU, 0xd7U, 0xa1U, 0x9dU, 0xe8U, 0xc4U, 0x55U,
|
|
||||||
0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU
|
|
||||||
)
|
|
||||||
// val xChaChaPoly = XChaCha20Poly1305Delegated(key, associatedData)
|
|
||||||
// val firstChunk = xChaChaPoly.encrypt(message)
|
|
||||||
// val finalChunk = xChaChaPoly.finishEncryption().first
|
|
||||||
// val result = firstChunk + finalChunk
|
|
||||||
// result.contentEquals(expected)
|
|
||||||
1 == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testStreamingImpl() = testBlocking {
|
|
||||||
Initializer.initialize()
|
|
||||||
val key = UByteArray(32) { 0U }
|
|
||||||
val state = ubyteArrayOf(
|
|
||||||
0x2DU, 0xDBU, 0xC7U, 0xB2U, 0x03U, 0xBCU, 0xC3U, 0x22U, 0xBDU, 0x0CU, 0xBAU, 0x82U, 0xADU, 0x77U, 0x79U, 0x44U,
|
|
||||||
0xE6U, 0x8FU, 0xA9U, 0x94U, 0x89U, 0xB1U, 0xDFU, 0xBEU, 0x00U, 0x9FU, 0x69U, 0xECU, 0x21U, 0x88U, 0x47U, 0x55U,
|
|
||||||
0x01U, 0x00U, 0x00U, 0x00U, 0xC5U, 0x55U, 0x06U, 0x38U, 0xEBU, 0xA3U, 0x12U, 0x7BU, 0x00U, 0x00U, 0x00U, 0x00U,
|
|
||||||
0x00U, 0x00U, 0x00U, 0x00U,
|
|
||||||
)
|
|
||||||
val header = ubyteArrayOf(
|
|
||||||
0x49U, 0x62U, 0x22U, 0x03U, 0xB7U, 0x46U, 0x11U, 0x97U, 0x8FU, 0x46U, 0x4AU, 0x3BU, 0x2FU, 0x2AU, 0x81U, 0x03U,
|
|
||||||
0xC5U, 0x55U, 0x06U, 0x38U, 0xEBU, 0xA3U, 0x12U, 0x7BU,
|
|
||||||
)
|
|
||||||
val expected = ubyteArrayOf(
|
|
||||||
0xAFU, 0xD3U, 0x2DU, 0x59U, 0xB8U, 0xC4U, 0x66U, 0x2EU, 0x47U, 0x29U, 0xC6U, 0xF9U, 0x93U, 0x4BU, 0x09U, 0x27U,
|
|
||||||
0x24U, 0xDDU, 0xF3U, 0x05U, 0x48U, 0x94U, 0x67U, 0x10U, 0x00U, 0x21U, 0x85U, 0x22U, 0x96U, 0x3CU, 0xCEU, 0x8EU,
|
|
||||||
0xB7U, 0x53U, 0x9DU, 0x46U, 0xF5U, 0x3CU, 0x5EU, 0x48U, 0x9BU, 0x8CU, 0x13U, 0xB7U, 0x28U, 0x6BU, 0xB3U, 0x6CU,
|
|
||||||
0x3AU, 0x04U, 0xB7U, 0x25U, 0xB9U, 0x50U, 0x45U, 0x08U, 0x0BU, 0x89U, 0xA2U, 0x0FU, 0x70U, 0xCCU, 0x60U, 0x1BU,
|
|
||||||
0xC3U, 0x17U, 0x35U, 0x9FU, 0xAEU, 0x82U, 0x51U, 0x43U, 0x1BU, 0x9DU, 0x53U, 0x9EU, 0xE2U, 0xAFU, 0x20U, 0x1FU,
|
|
||||||
0xFDU, 0x03U, 0x59U, 0x11U, 0x51U, 0x9EU, 0xACU, 0x83U, 0xCDU, 0x78U, 0xD1U, 0xD0U, 0xE5U, 0xD7U, 0x0EU, 0x41U,
|
|
||||||
0xDEU, 0xFBU, 0x5CU, 0x7FU, 0x1CU, 0x26U, 0x32U, 0x2CU, 0x51U, 0xF6U, 0xEFU, 0xC6U, 0x34U, 0xC4U, 0xACU, 0x6CU,
|
|
||||||
0xE8U, 0xF9U, 0x4BU, 0xABU, 0xA3U,
|
|
||||||
)
|
|
||||||
val encryptor = XChaCha20Poly1305Delegated(key, state, header, false)
|
|
||||||
val decryptor = XChaCha20Poly1305Delegated(key, state, header, true)
|
|
||||||
val data = UByteArray(100) { 0U }
|
|
||||||
val result = encryptor.encrypt(data)
|
|
||||||
val decrypted = decryptor.decrypt(result)
|
|
||||||
println("Encrypted -----------")
|
|
||||||
result.hexColumsPrint()
|
|
||||||
println("Encrypted end -----------")
|
|
||||||
println("Decrypted -----------")
|
|
||||||
decrypted.hexColumsPrint()
|
|
||||||
println("Decrypted end -----------")
|
|
||||||
assertTrue {
|
|
||||||
expected.contentEquals(result) && decrypted.contentEquals(data)
|
|
||||||
}
|
|
||||||
val messedUpTag = result.copyOf()
|
|
||||||
messedUpTag[messedUpTag.size - 3] = 0U
|
|
||||||
messedUpTag[messedUpTag.size - 2] = 0U
|
|
||||||
messedUpTag[messedUpTag.size - 1] = 0U
|
|
||||||
assertFails {
|
|
||||||
val decryptorForWrongTag = XChaCha20Poly1305Delegated(key, state, header, true)
|
|
||||||
val plaintext = decryptorForWrongTag.decrypt(messedUpTag)
|
|
||||||
println("Decrypted with wrong tag -----------")
|
|
||||||
plaintext.hexColumsPrint()
|
|
||||||
println("Decrypted with wrong tag end -----------")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.blake2b
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.Crypto
|
|
||||||
import com.ionspin.kotlin.crypto.CryptoPrimitives
|
|
||||||
import com.ionspin.kotlin.crypto.Initializer
|
|
||||||
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
|
||||||
import com.ionspin.kotlin.crypto.util.testBlocking
|
|
||||||
import com.ionspin.kotlin.crypto.util.toHexString
|
|
||||||
import kotlin.test.BeforeTest
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 09-Jun-2020
|
|
||||||
*/
|
|
||||||
class Blake2bTest {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun statelessSimpleTest() = testBlocking {
|
|
||||||
Initializer.initialize()
|
|
||||||
val expected = "a71079d42853dea26e453004338670a53814b78137ffbed07603a41d76a483aa9bc33b582f77d30a65e6f29a89" +
|
|
||||||
"6c0411f38312e1d66e0bf16386c86a89bea572"
|
|
||||||
val result = CryptoPrimitives.Blake2b.stateless("test".encodeToUByteArray()).toHexString()
|
|
||||||
// println("Result: $result")
|
|
||||||
assertTrue { result == expected }
|
|
||||||
}
|
|
||||||
|
|
||||||
//This is a bad test since it's not larger than one block
|
|
||||||
//but for now I'm testing that the platform library is being correctly called
|
|
||||||
@Test
|
|
||||||
fun updateableSimpleTest() = testBlocking {
|
|
||||||
Initializer.initialize()
|
|
||||||
val expected = "a71079d42853dea26e453004338670a53814b78137ffbed07603a41d76a483aa9bc33b582f77d30a65e6f29a89" +
|
|
||||||
"6c0411f38312e1d66e0bf16386c86a89bea572"
|
|
||||||
val blake2b = CryptoPrimitives.Blake2b.updateable()
|
|
||||||
blake2b.update("t".encodeToUByteArray())
|
|
||||||
blake2b.update(("est".encodeToUByteArray()))
|
|
||||||
val result = blake2b.digest().toHexString()
|
|
||||||
// println("Result: $result")
|
|
||||||
assertTrue { result == expected }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.sha
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.Crypto
|
|
||||||
import com.ionspin.kotlin.crypto.CryptoPrimitives
|
|
||||||
import com.ionspin.kotlin.crypto.Initializer
|
|
||||||
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
|
||||||
import com.ionspin.kotlin.crypto.util.testBlocking
|
|
||||||
import com.ionspin.kotlin.crypto.util.toHexString
|
|
||||||
import kotlin.test.BeforeTest
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 07-Jun-2020
|
|
||||||
*/
|
|
||||||
class Sha256Test {
|
|
||||||
@BeforeTest
|
|
||||||
fun beforeTest() = testBlocking {
|
|
||||||
Initializer.initialize()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun statelessSimpleTest() = testBlocking {
|
|
||||||
Initializer.initialize()
|
|
||||||
val expected = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
|
|
||||||
val result = CryptoPrimitives.Sha256.stateless("test".encodeToUByteArray()).toHexString()
|
|
||||||
// println("Result: $result")
|
|
||||||
assertTrue { result == expected }
|
|
||||||
}
|
|
||||||
|
|
||||||
//This is a bad test since it's not larger than one block
|
|
||||||
//but for now I'm testing that the platform library is being correctly called
|
|
||||||
@Test
|
|
||||||
fun updateableSimpleTest() = testBlocking {
|
|
||||||
Initializer.initialize()
|
|
||||||
val expected = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
|
|
||||||
val sha256 = CryptoPrimitives.Sha256.updateable()
|
|
||||||
sha256.update("t".encodeToUByteArray())
|
|
||||||
sha256.update(("est".encodeToUByteArray()))
|
|
||||||
val result = sha256.digest().toHexString()
|
|
||||||
// println("Result: $result")
|
|
||||||
assertTrue { result == expected }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.sha
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.Crypto
|
|
||||||
import com.ionspin.kotlin.crypto.CryptoPrimitives
|
|
||||||
import com.ionspin.kotlin.crypto.Initializer
|
|
||||||
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
|
||||||
import com.ionspin.kotlin.crypto.util.testBlocking
|
|
||||||
import com.ionspin.kotlin.crypto.util.toHexString
|
|
||||||
import kotlin.test.BeforeTest
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 07-Jun-2020
|
|
||||||
*/
|
|
||||||
class Sha512Test {
|
|
||||||
@BeforeTest
|
|
||||||
fun beforeTest() = testBlocking {
|
|
||||||
Initializer.initialize()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun statelessSimpleTest() = testBlocking {
|
|
||||||
Initializer.initialize()
|
|
||||||
val expected = "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67" +
|
|
||||||
"b143732c304cc5fa9ad8e6f57f50028a8ff"
|
|
||||||
val result = CryptoPrimitives.Sha512.stateless("test".encodeToUByteArray()).toHexString()
|
|
||||||
// println("Result: $result")
|
|
||||||
assertTrue { result == expected }
|
|
||||||
}
|
|
||||||
|
|
||||||
//This is a bad test since it's not larger than one block
|
|
||||||
//but for now I'm testing that the platform library is being correctly called
|
|
||||||
@Test
|
|
||||||
fun updateableSimpleTest() = testBlocking {
|
|
||||||
Initializer.initialize()
|
|
||||||
val expected = "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67" +
|
|
||||||
"b143732c304cc5fa9ad8e6f57f50028a8ff"
|
|
||||||
val sha512 = CryptoPrimitives.Sha512.updateable()
|
|
||||||
sha512.update("t".encodeToUByteArray())
|
|
||||||
sha512.update(("est".encodeToUByteArray()))
|
|
||||||
val result = sha512.digest().toHexString()
|
|
||||||
// println("Result: $result")
|
|
||||||
assertTrue { result == expected }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.highlevel
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.Crypto
|
|
||||||
import com.ionspin.kotlin.crypto.Initializer
|
|
||||||
import com.ionspin.kotlin.crypto.SymmetricKey
|
|
||||||
import com.ionspin.kotlin.crypto.hash.decodeToString
|
|
||||||
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
|
||||||
import com.ionspin.kotlin.crypto.util.hexColumsPrint
|
|
||||||
import com.ionspin.kotlin.crypto.util.testBlocking
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 09-Jul-2020
|
|
||||||
*/
|
|
||||||
class EncryptionTest {
|
|
||||||
@Test
|
|
||||||
fun testMultipartEncryption() = testBlocking {
|
|
||||||
Initializer.initialize()
|
|
||||||
val plaintext = ("pUoR4JVXJUeMKNkt6ZGGzEdTo33ajNGXwXpivBKA0XKs8toGRYI9Eul4bELRDkaQDNhd4vZseEFU" +
|
|
||||||
"ojsAn3c9zIifIrMnydSivHVZ2pBtpAQwYoJhYmEsfE0tROGnOwFWyB9K6LRSv1gB3YqKR9VyM8mpRoUM3UCRRjyiX7bnKdCE1" +
|
|
||||||
"EiX0myiwcY1nUKTgB3keERWtMU07hX7bCtao5nRvDofSj3o3IInHRQh6opltr5asQwn4m1qn029QF").encodeToUByteArray()
|
|
||||||
val associatedData = "Additional data 1".encodeToUByteArray()
|
|
||||||
val keyValue = UByteArray(32) { it.toUByte() }
|
|
||||||
val key = SymmetricKey(keyValue)
|
|
||||||
val encryptor = Crypto.Encryption.createMultipartEncryptor(key)
|
|
||||||
val header = encryptor.startEncryption()
|
|
||||||
val ciphertext1 = encryptor.encryptPartialData(plaintext.sliceArray(0 until 100), associatedData)
|
|
||||||
val ciphertext2 = encryptor.encryptPartialData(plaintext.sliceArray(100 until 200))
|
|
||||||
val ciphertext3 = encryptor.encryptPartialData(plaintext.sliceArray(200 until 250))
|
|
||||||
//decrypt
|
|
||||||
val decryptor = Crypto.Encryption.createMultipartDecryptor(key, header)
|
|
||||||
val plaintext1 = decryptor.decryptPartialData(ciphertext1, associatedData)
|
|
||||||
val plaintext2 = decryptor.decryptPartialData(ciphertext2)
|
|
||||||
val plaintext3 = decryptor.decryptPartialData(ciphertext3)
|
|
||||||
|
|
||||||
val combinedPlaintext = plaintext1.data + plaintext2.data + plaintext3.data
|
|
||||||
assertTrue {
|
|
||||||
plaintext.contentEquals(combinedPlaintext)
|
|
||||||
}
|
|
||||||
encryptor.cleanup()
|
|
||||||
decryptor.cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto.util
|
|
||||||
|
|
||||||
import kotlin.coroutines.Continuation
|
|
||||||
import kotlin.coroutines.EmptyCoroutineContext
|
|
||||||
import kotlin.coroutines.startCoroutine
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 20-Jul-2019
|
|
||||||
*/
|
|
||||||
fun testBlocking(block : suspend () -> Unit) {
|
|
||||||
val continuation = Continuation<Unit>(EmptyCoroutineContext) {
|
|
||||||
//Do nothing
|
|
||||||
if (it.isFailure) {
|
|
||||||
throw it.exceptionOrNull()!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
block.startCoroutine(continuation)
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import ext.libsodium.com.ionspin.kotlin.crypto.JsSodiumInterface
|
|
||||||
import ext.libsodium.com.ionspin.kotlin.crypto.JsSodiumLoader
|
|
||||||
/* 1.4-M1 has some weirdness with static/objects, or I'm misusing something, not sure */
|
|
||||||
lateinit var sodiumPointer : JsSodiumInterface
|
|
||||||
var sodiumLoaded: Boolean = false
|
|
||||||
|
|
||||||
fun getSodium() : JsSodiumInterface = sodiumPointer
|
|
||||||
|
|
||||||
//fun getSodiumAdvanced() : JsSodiumAdvancedInterface = js("sodiumPointer.libsodium")
|
|
||||||
|
|
||||||
fun setSodiumPointer(jsSodiumInterface: JsSodiumInterface) {
|
|
||||||
js("sodiumPointer = jsSodiumInterface")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSodiumLoaded() : Boolean = sodiumLoaded
|
|
||||||
|
|
||||||
fun setSodiumLoaded(loaded: Boolean) {
|
|
||||||
js("sodiumLoaded = loaded")
|
|
||||||
}
|
|
||||||
|
|
||||||
actual object Initializer {
|
|
||||||
private var isPlatformInitialized = false
|
|
||||||
|
|
||||||
actual suspend fun initialize() {
|
|
||||||
JsSodiumLoader.load()
|
|
||||||
isPlatformInitialized = true
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun initializeWithCallback(done: () -> Unit) {
|
|
||||||
JsSodiumLoader.loadWithCallback {
|
|
||||||
isPlatformInitialized = true
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun isInitialized(): Boolean {
|
|
||||||
return isPlatformInitialized
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
package ext.libsodium.com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
|
|
||||||
import org.khronos.webgl.Uint8Array
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 27-May-2020
|
|
||||||
*/
|
|
||||||
interface JsSodiumInterface {
|
|
||||||
|
|
||||||
fun randombytes_buf(numberOfBytes: Int): Uint8Array
|
|
||||||
|
|
||||||
fun crypto_generichash(hashLength: Int, inputMessage: Uint8Array, key: Uint8Array,): Uint8Array
|
|
||||||
|
|
||||||
fun crypto_hash_sha256(message: Uint8Array): Uint8Array
|
|
||||||
|
|
||||||
fun crypto_hash_sha512(message: Uint8Array): Uint8Array
|
|
||||||
|
|
||||||
//Updateable
|
|
||||||
|
|
||||||
fun crypto_generichash_init(key : Uint8Array, hashLength: Int) : dynamic
|
|
||||||
|
|
||||||
fun crypto_generichash_update(state: dynamic, inputMessage: Uint8Array)
|
|
||||||
|
|
||||||
fun crypto_generichash_final(state: dynamic, hashLength: Int) : Uint8Array
|
|
||||||
|
|
||||||
|
|
||||||
fun crypto_hash_sha256_init() : dynamic
|
|
||||||
|
|
||||||
fun crypto_hash_sha256_update(state: dynamic, message: Uint8Array)
|
|
||||||
|
|
||||||
fun crypto_hash_sha256_final(state: dynamic): Uint8Array
|
|
||||||
|
|
||||||
fun crypto_hash_sha512_init() : dynamic
|
|
||||||
|
|
||||||
fun crypto_hash_sha512_update(state: dynamic, message: Uint8Array)
|
|
||||||
|
|
||||||
fun crypto_hash_sha512_final(state: dynamic): Uint8Array
|
|
||||||
|
|
||||||
//XChaCha20Poly1305
|
|
||||||
fun crypto_aead_xchacha20poly1305_ietf_encrypt(message: Uint8Array, associatedData: Uint8Array, secretNonce: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
|
|
||||||
fun crypto_aead_xchacha20poly1305_ietf_decrypt(secretNonce: Uint8Array, ciphertext: Uint8Array, associatedData: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
|
|
||||||
|
|
||||||
//XChaCha20Poly1305
|
|
||||||
//encrypt
|
|
||||||
fun crypto_secretstream_xchacha20poly1305_init_push(header: Uint8Array) : dynamic
|
|
||||||
fun crypto_secretstream_xchacha20poly1305_push(state: dynamic, message: Uint8Array, associatedData: Uint8Array, tag: UByte) : Uint8Array
|
|
||||||
|
|
||||||
//decrypt
|
|
||||||
fun crypto_secretstream_xchacha20poly1305_init_pull(header: Uint8Array, key: Uint8Array) : dynamic
|
|
||||||
fun crypto_secretstream_xchacha20poly1305_pull(state: dynamic, ciphertext: Uint8Array, associatedData: Uint8Array) : dynamic
|
|
||||||
|
|
||||||
//util
|
|
||||||
fun memzero(array: Uint8Array)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
package ext.libsodium.com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.getSodiumLoaded
|
|
||||||
import com.ionspin.kotlin.crypto.setSodiumPointer
|
|
||||||
import com.ionspin.kotlin.crypto.sodiumLoaded
|
|
||||||
import ext.libsodium.*
|
|
||||||
import kotlin.coroutines.Continuation
|
|
||||||
import kotlin.coroutines.suspendCoroutine
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 27-May-2020
|
|
||||||
*/
|
|
||||||
object JsSodiumLoader {
|
|
||||||
|
|
||||||
class _EmitJsSodiumFunction {
|
|
||||||
init {
|
|
||||||
println(::crypto_generichash)
|
|
||||||
println(::crypto_hash_sha256)
|
|
||||||
println(::crypto_hash_sha512)
|
|
||||||
println(::crypto_hash_sha256_init)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun storeSodium(promisedSodium: dynamic, continuation: Continuation<Unit>) {
|
|
||||||
setSodiumPointer(promisedSodium)
|
|
||||||
sodiumLoaded = true
|
|
||||||
continuation.resumeWith(Result.success(Unit))
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun load() = suspendCoroutine<Unit> { continuation ->
|
|
||||||
console.log(getSodiumLoaded())
|
|
||||||
if (!getSodiumLoaded()) {
|
|
||||||
val libsodiumModule = js("\$module\$libsodium_wrappers_sumo")
|
|
||||||
_libsodiumPromise.then<dynamic> { storeSodium(libsodiumModule, continuation) }
|
|
||||||
} else {
|
|
||||||
continuation.resumeWith(Result.success(Unit))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadWithCallback(doneCallback: () -> (Unit)) {
|
|
||||||
console.log(getSodiumLoaded())
|
|
||||||
if (!getSodiumLoaded()) {
|
|
||||||
val libsodiumModule = js("\$module\$libsodium_wrappers_sumo")
|
|
||||||
_libsodiumPromise.then<dynamic> {
|
|
||||||
setSodiumPointer(libsodiumModule)
|
|
||||||
sodiumLoaded = true
|
|
||||||
doneCallback.invoke()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
doneCallback.invoke()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
package ext.libsodium.com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import org.khronos.webgl.Uint8Array
|
|
||||||
import org.khronos.webgl.get
|
|
||||||
import org.khronos.webgl.set
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 25-Jun-2020
|
|
||||||
*
|
|
||||||
* TODO investigate using unsafe cast
|
|
||||||
*/
|
|
||||||
fun UByteArray.toUInt8Array() : Uint8Array {
|
|
||||||
val uint8Result = Uint8Array(toByteArray().toTypedArray())
|
|
||||||
return uint8Result
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun Uint8Array.toUByteArray() : UByteArray {
|
|
||||||
val result = UByteArray(length)
|
|
||||||
for (i in 0 until length) {
|
|
||||||
result[i] = get(i).toUByte()
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import org.khronos.webgl.get
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 21-Sep-2019
|
|
||||||
*/
|
|
||||||
actual object SRNG {
|
|
||||||
var counter = 0
|
|
||||||
|
|
||||||
actual fun getRandomBytes(amount: Int): UByteArray {
|
|
||||||
val randomBytes = getSodium().randombytes_buf(amount)
|
|
||||||
val randomBytesUByteArray = UByteArray(amount) {
|
|
||||||
0U
|
|
||||||
}
|
|
||||||
for (i in 0 until amount) {
|
|
||||||
js("""
|
|
||||||
randomBytesUByteArray[i] = randomBytes[i]
|
|
||||||
""")
|
|
||||||
}
|
|
||||||
return randomBytesUByteArray
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,130 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.authenticated
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.InvalidTagException
|
|
||||||
import com.ionspin.kotlin.crypto.getSodium
|
|
||||||
import com.ionspin.kotlin.crypto.util.hexColumsPrint
|
|
||||||
import ext.libsodium.com.ionspin.kotlin.crypto.toUByteArray
|
|
||||||
import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array
|
|
||||||
import org.khronos.webgl.Uint8Array
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 25-Jun-2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 14-Jun-2020
|
|
||||||
*/
|
|
||||||
actual class XChaCha20Poly1305Delegated internal actual constructor() {
|
|
||||||
actual companion object {
|
|
||||||
actual fun encrypt(
|
|
||||||
key: UByteArray,
|
|
||||||
nonce: UByteArray,
|
|
||||||
message: UByteArray,
|
|
||||||
associatedData: UByteArray
|
|
||||||
): UByteArray {
|
|
||||||
val encrypted = getSodium().crypto_aead_xchacha20poly1305_ietf_encrypt(
|
|
||||||
message.toUInt8Array(),
|
|
||||||
associatedData.toUInt8Array(),
|
|
||||||
Uint8Array(0),
|
|
||||||
nonce.toUInt8Array(),
|
|
||||||
key.toUInt8Array()
|
|
||||||
)
|
|
||||||
return encrypted.toUByteArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun decrypt(
|
|
||||||
key: UByteArray,
|
|
||||||
nonce: UByteArray,
|
|
||||||
ciphertext: UByteArray,
|
|
||||||
associatedData: UByteArray
|
|
||||||
): UByteArray {
|
|
||||||
val decrypted = getSodium().crypto_aead_xchacha20poly1305_ietf_decrypt(
|
|
||||||
Uint8Array(0),
|
|
||||||
ciphertext.toUInt8Array(),
|
|
||||||
associatedData.toUInt8Array(),
|
|
||||||
nonce.toUInt8Array(),
|
|
||||||
key.toUInt8Array()
|
|
||||||
)
|
|
||||||
return decrypted.toUByteArray()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var state : dynamic = null
|
|
||||||
var isInitialized = false
|
|
||||||
var isEncryptor = false
|
|
||||||
|
|
||||||
actual fun initializeForEncryption(key: UByteArray) : UByteArray {
|
|
||||||
println("Initializaing for encryption")
|
|
||||||
val stateAndHeader = getSodium().crypto_secretstream_xchacha20poly1305_init_push(key.toUInt8Array())
|
|
||||||
state = stateAndHeader.state
|
|
||||||
val header = stateAndHeader.header as Uint8Array
|
|
||||||
console.log(state)
|
|
||||||
console.log(header)
|
|
||||||
println("Done initializaing for encryption")
|
|
||||||
isInitialized = true
|
|
||||||
isEncryptor = true
|
|
||||||
return header.toUByteArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun initializeForDecryption(key: UByteArray, header: UByteArray) {
|
|
||||||
println("Initializing for decryption")
|
|
||||||
header.hexColumsPrint()
|
|
||||||
state = getSodium().crypto_secretstream_xchacha20poly1305_init_pull(header.toUInt8Array(), key.toUInt8Array())
|
|
||||||
console.log(state)
|
|
||||||
isInitialized = true
|
|
||||||
isEncryptor = false
|
|
||||||
}
|
|
||||||
|
|
||||||
internal actual constructor(
|
|
||||||
key: UByteArray,
|
|
||||||
testState: UByteArray,
|
|
||||||
testHeader: UByteArray,
|
|
||||||
isDecryptor: Boolean
|
|
||||||
) : this() {
|
|
||||||
state = getSodium().crypto_secretstream_xchacha20poly1305_init_pull(testHeader.toUInt8Array(), key.toUInt8Array())
|
|
||||||
console.log(state)
|
|
||||||
println("Done initializaing test state")
|
|
||||||
isInitialized = true
|
|
||||||
isEncryptor = !isDecryptor
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun encrypt(data: UByteArray, associatedData: UByteArray): UByteArray {
|
|
||||||
if (!isInitialized) {
|
|
||||||
throw RuntimeException("Not initalized!")
|
|
||||||
}
|
|
||||||
if (!isEncryptor) {
|
|
||||||
throw RuntimeException("Initialized as decryptor, attempted to use as encryptor")
|
|
||||||
}
|
|
||||||
val encrypted = getSodium().crypto_secretstream_xchacha20poly1305_push(state, data.toUInt8Array(), associatedData.toUInt8Array(), 0U)
|
|
||||||
return encrypted.toUByteArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun decrypt(data: UByteArray, associatedData: UByteArray): UByteArray {
|
|
||||||
if (!isInitialized) {
|
|
||||||
throw RuntimeException("Not initalized!")
|
|
||||||
}
|
|
||||||
if (isEncryptor) {
|
|
||||||
throw RuntimeException("Initialized as encryptor, attempted to use as decryptor")
|
|
||||||
}
|
|
||||||
val decryptedWithTag = getSodium().crypto_secretstream_xchacha20poly1305_pull(state, data.toUInt8Array(), associatedData.toUInt8Array())
|
|
||||||
val decrypted = decryptedWithTag.message as Uint8Array
|
|
||||||
val validTag = decryptedWithTag.tag
|
|
||||||
|
|
||||||
if (validTag != 0U) {
|
|
||||||
println("Tag validation failed")
|
|
||||||
throw InvalidTagException()
|
|
||||||
}
|
|
||||||
return decrypted.toUByteArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun cleanup() {
|
|
||||||
//TODO JS cleanup
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.blake2b
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.getSodium
|
|
||||||
import org.khronos.webgl.Uint8Array
|
|
||||||
import org.khronos.webgl.get
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 14-Jul-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
actual class Blake2bDelegated actual constructor(key: UByteArray?, val hashLength: Int) : Blake2bMultipart {
|
|
||||||
override val MAX_HASH_BYTES: Int = 64
|
|
||||||
|
|
||||||
|
|
||||||
val state : dynamic
|
|
||||||
|
|
||||||
init {
|
|
||||||
state = getSodium().crypto_generichash_init(
|
|
||||||
Uint8Array(key?.toByteArray()?.toTypedArray() ?: arrayOf()),
|
|
||||||
hashLength
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(data: UByteArray) {
|
|
||||||
getSodium().crypto_generichash_update(state, Uint8Array(data.toByteArray().toTypedArray()))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun digest(): UByteArray {
|
|
||||||
val hashed = getSodium().crypto_generichash_final(state, hashLength)
|
|
||||||
val hash = UByteArray(hashLength)
|
|
||||||
for (i in 0 until hashLength) {
|
|
||||||
hash[i] = hashed[i].toUByte()
|
|
||||||
}
|
|
||||||
return hash
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
actual object Blake2bDelegatedStateless : Blake2b {
|
|
||||||
override val MAX_HASH_BYTES: Int = 64
|
|
||||||
|
|
||||||
override fun digest(inputMessage: UByteArray, key: UByteArray, hashLength: Int): UByteArray {
|
|
||||||
val hashed = getSodium().crypto_generichash(hashLength,
|
|
||||||
Uint8Array(inputMessage.toByteArray().toTypedArray()),
|
|
||||||
Uint8Array(key.toByteArray().toTypedArray())
|
|
||||||
)
|
|
||||||
val hash = UByteArray(hashLength)
|
|
||||||
for (i in 0 until hashLength) {
|
|
||||||
hash[i] = hashed[i].toUByte()
|
|
||||||
}
|
|
||||||
return hash
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.sha
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.getSodium
|
|
||||||
|
|
||||||
import org.khronos.webgl.Uint8Array
|
|
||||||
import org.khronos.webgl.get
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 17-Jul-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
actual class Sha256Delegated : Sha256 {
|
|
||||||
|
|
||||||
val state : dynamic
|
|
||||||
|
|
||||||
init {
|
|
||||||
state = getSodium().crypto_hash_sha256_init()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(data: UByteArray) {
|
|
||||||
getSodium().crypto_hash_sha256_update(state, Uint8Array(data.toByteArray().toTypedArray()))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun digest(): UByteArray {
|
|
||||||
val hashed = getSodium().crypto_hash_sha256_final(state)
|
|
||||||
val hash = UByteArray(Sha256StatelessDelegated.MAX_HASH_BYTES)
|
|
||||||
console.log(hashed)
|
|
||||||
for (i in 0 until Sha256StatelessDelegated.MAX_HASH_BYTES) {
|
|
||||||
hash[i] = hashed[i].toUByte()
|
|
||||||
}
|
|
||||||
return hash
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
actual object Sha256StatelessDelegated : StatelessSha256 {
|
|
||||||
|
|
||||||
override fun digest(inputMessage: UByteArray): UByteArray {
|
|
||||||
val hashed = getSodium().crypto_hash_sha256(Uint8Array(inputMessage.toByteArray().toTypedArray()))
|
|
||||||
val hash = UByteArray(MAX_HASH_BYTES)
|
|
||||||
for (i in 0 until MAX_HASH_BYTES) {
|
|
||||||
hash[i] = hashed[i].toUByte()
|
|
||||||
}
|
|
||||||
return hash
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.sha
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.getSodium
|
|
||||||
|
|
||||||
import org.khronos.webgl.Uint8Array
|
|
||||||
import org.khronos.webgl.get
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 17-Jul-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
actual class Sha512Delegated : Sha512Multipart {
|
|
||||||
val state : dynamic
|
|
||||||
|
|
||||||
init {
|
|
||||||
state = getSodium().crypto_hash_sha512_init()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(data: UByteArray) {
|
|
||||||
getSodium().crypto_hash_sha512_update(state, Uint8Array(data.toByteArray().toTypedArray()))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun digest(): UByteArray {
|
|
||||||
val hashed = getSodium().crypto_hash_sha512_final(state)
|
|
||||||
val hash = UByteArray(Sha512StatelessDelegated.MAX_HASH_BYTES)
|
|
||||||
for (i in 0 until Sha512StatelessDelegated.MAX_HASH_BYTES) {
|
|
||||||
hash[i] = hashed[i].toUByte()
|
|
||||||
}
|
|
||||||
return hash
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
actual object Sha512StatelessDelegated : Sha512 {
|
|
||||||
|
|
||||||
override fun digest(inputMessage: UByteArray): UByteArray {
|
|
||||||
val hashed = getSodium().crypto_hash_sha512(Uint8Array(inputMessage.toByteArray().toTypedArray()))
|
|
||||||
val hash = UByteArray(Sha512StatelessDelegated.MAX_HASH_BYTES)
|
|
||||||
for (i in 0 until Sha512StatelessDelegated.MAX_HASH_BYTES) {
|
|
||||||
hash[i] = hashed[i].toUByte()
|
|
||||||
}
|
|
||||||
return hash
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
@file:JsModule("libsodium-wrappers-sumo")
|
|
||||||
@file:JsNonModule
|
|
||||||
package ext.libsodium
|
|
||||||
|
|
||||||
import org.khronos.webgl.Uint8Array
|
|
||||||
import kotlin.js.Promise
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 25-May-2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
@JsName("ready")
|
|
||||||
external val _libsodiumPromise : Promise<dynamic>
|
|
||||||
|
|
||||||
external fun crypto_generichash(hashLength: Int, inputMessage: Uint8Array) : Uint8Array
|
|
||||||
|
|
||||||
external fun crypto_hash_sha256(message: Uint8Array) : Uint8Array
|
|
||||||
external fun crypto_hash_sha512(message: Uint8Array) : Uint8Array
|
|
||||||
|
|
||||||
external fun crypto_hash_sha256_init(): dynamic
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.util.testBlocking
|
|
||||||
import ext.libsodium.com.ionspin.kotlin.crypto.JsSodiumLoader
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 05-Jan-2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
class SRNGJsTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testJsSrng() = testBlocking {
|
|
||||||
JsSodiumLoader.load()
|
|
||||||
val bytes1 = SRNG.getRandomBytes(10)
|
|
||||||
val bytes2 = SRNG.getRandomBytes(10)
|
|
||||||
// println("BYTES1\n")
|
|
||||||
// bytes1.forEach {
|
|
||||||
// print(it.toString(16).padStart(2, '0'))
|
|
||||||
// }
|
|
||||||
// println("BYTES2\n")
|
|
||||||
// bytes2.forEach {
|
|
||||||
// print(it.toString(16).padStart(2, '0'))
|
|
||||||
// }
|
|
||||||
assertTrue {
|
|
||||||
!bytes1.contentEquals(bytes2) &&
|
|
||||||
bytes1.size == 10 &&
|
|
||||||
bytes2.size == 10
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto.util
|
|
||||||
//
|
|
||||||
//import kotlinx.coroutines.GlobalScope
|
|
||||||
//import kotlinx.coroutines.promise
|
|
||||||
//
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * Created by Ugljesa Jovanovic
|
|
||||||
// * ugljesa.jovanovic@ionspin.com
|
|
||||||
// * on 20-Jul-2019
|
|
||||||
// */
|
|
||||||
//actual fun testBlocking(block: suspend ()-> Unit) : dynamic = GlobalScope.promise { block() }
|
|
@ -1,25 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import com.goterl.lazycode.lazysodium.SodiumJava
|
|
||||||
|
|
||||||
actual object Initializer {
|
|
||||||
private var isPlatformInitialized = false
|
|
||||||
|
|
||||||
lateinit var sodium : SodiumJava
|
|
||||||
actual suspend fun initialize() {
|
|
||||||
sodium = SodiumJava()
|
|
||||||
isPlatformInitialized = true
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun initializeWithCallback(done: () -> Unit) {
|
|
||||||
sodium = SodiumJava()
|
|
||||||
isPlatformInitialized = true
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun isInitialized(): Boolean {
|
|
||||||
return isPlatformInitialized
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import java.security.SecureRandom
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 21-Sep-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
actual object SRNG {
|
|
||||||
val secureRandom = SecureRandom()
|
|
||||||
actual fun getRandomBytes(amount: Int): UByteArray {
|
|
||||||
val byteArray = ByteArray(amount)
|
|
||||||
secureRandom.nextBytes(byteArray)
|
|
||||||
return byteArray.asUByteArray()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,142 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.authenticated
|
|
||||||
|
|
||||||
import com.goterl.lazycode.lazysodium.SodiumJava
|
|
||||||
import com.goterl.lazycode.lazysodium.interfaces.SecretStream
|
|
||||||
import com.ionspin.kotlin.crypto.InvalidTagException
|
|
||||||
import com.ionspin.kotlin.crypto.util.hexColumsPrint
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 14-Jun-2020
|
|
||||||
*/
|
|
||||||
actual class XChaCha20Poly1305Delegated internal actual constructor() {
|
|
||||||
actual companion object {
|
|
||||||
actual fun encrypt(
|
|
||||||
key: UByteArray,
|
|
||||||
nonce: UByteArray,
|
|
||||||
message: UByteArray,
|
|
||||||
associatedData: UByteArray
|
|
||||||
): UByteArray {
|
|
||||||
val ciphertext = ByteArray(message.size + 16)
|
|
||||||
SodiumJava().crypto_aead_xchacha20poly1305_ietf_encrypt(
|
|
||||||
ciphertext,
|
|
||||||
longArrayOf(ciphertext.size.toLong()),
|
|
||||||
message.toByteArray(),
|
|
||||||
message.size.toLong(),
|
|
||||||
associatedData.toByteArray(),
|
|
||||||
associatedData.size.toLong(),
|
|
||||||
null,
|
|
||||||
nonce.toByteArray(),
|
|
||||||
key.toByteArray()
|
|
||||||
|
|
||||||
)
|
|
||||||
return ciphertext.asUByteArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun decrypt(
|
|
||||||
key: UByteArray,
|
|
||||||
nonce: UByteArray,
|
|
||||||
ciphertext: UByteArray,
|
|
||||||
associatedData: UByteArray
|
|
||||||
): UByteArray {
|
|
||||||
val message = ByteArray(ciphertext.size - 16)
|
|
||||||
SodiumJava().crypto_aead_xchacha20poly1305_ietf_decrypt(
|
|
||||||
message,
|
|
||||||
longArrayOf(ciphertext.size.toLong()),
|
|
||||||
null,
|
|
||||||
ciphertext.toByteArray(),
|
|
||||||
ciphertext.size.toLong(),
|
|
||||||
associatedData.toByteArray(),
|
|
||||||
associatedData.size.toLong(),
|
|
||||||
nonce.toByteArray(),
|
|
||||||
key.toByteArray()
|
|
||||||
|
|
||||||
)
|
|
||||||
return message.asUByteArray()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val state : SecretStream.State = SecretStream.State()
|
|
||||||
val sodium = SodiumJava()
|
|
||||||
|
|
||||||
var isInitialized = false
|
|
||||||
var isEncryptor = false
|
|
||||||
|
|
||||||
internal actual constructor(
|
|
||||||
key: UByteArray,
|
|
||||||
testState: UByteArray,
|
|
||||||
testHeader: UByteArray,
|
|
||||||
isDecryptor: Boolean
|
|
||||||
) : this() {
|
|
||||||
state.k = testState.sliceArray(0 until 32).toByteArray()
|
|
||||||
state.nonce = testState.sliceArray(32 until 44).toByteArray()
|
|
||||||
isInitialized = true
|
|
||||||
isEncryptor = !isDecryptor
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun initializeForEncryption(key: UByteArray) : UByteArray {
|
|
||||||
val header = UByteArray(24)
|
|
||||||
sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header.asByteArray(), key.asByteArray())
|
|
||||||
isInitialized = true
|
|
||||||
isEncryptor = true
|
|
||||||
return header
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun initializeForDecryption(key: UByteArray, header: UByteArray) {
|
|
||||||
sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header.asByteArray(), key.asByteArray())
|
|
||||||
isInitialized = true
|
|
||||||
isEncryptor = false
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun encrypt(data: UByteArray, associatedData: UByteArray): UByteArray {
|
|
||||||
if (!isInitialized) {
|
|
||||||
throw RuntimeException("Not initalized!")
|
|
||||||
}
|
|
||||||
if (!isEncryptor) {
|
|
||||||
throw RuntimeException("Initialized as decryptor, attempted to use as encryptor")
|
|
||||||
}
|
|
||||||
val ciphertext = ByteArray(1 + data.size + 16)
|
|
||||||
sodium.crypto_secretstream_xchacha20poly1305_push(
|
|
||||||
state, ciphertext, null,
|
|
||||||
data.asByteArray(), data.size.toLong(),
|
|
||||||
associatedData.asByteArray(), associatedData.size.toLong(),
|
|
||||||
0
|
|
||||||
)
|
|
||||||
return ciphertext.asUByteArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun decrypt(data: UByteArray, associatedData: UByteArray): UByteArray {
|
|
||||||
if (!isInitialized) {
|
|
||||||
throw RuntimeException("Not initalized!")
|
|
||||||
}
|
|
||||||
if (isEncryptor) {
|
|
||||||
throw RuntimeException("Initialized as encryptor, attempted to use as decryptor")
|
|
||||||
}
|
|
||||||
val plaintext = ByteArray(data.size - 17)
|
|
||||||
|
|
||||||
val validTag = sodium.crypto_secretstream_xchacha20poly1305_pull(
|
|
||||||
state, plaintext, null,
|
|
||||||
null,
|
|
||||||
data.asByteArray(),
|
|
||||||
(data.size).toLong(),
|
|
||||||
associatedData.asByteArray(),
|
|
||||||
associatedData.size.toLong()
|
|
||||||
)
|
|
||||||
if (validTag != 0) {
|
|
||||||
println("Tag validation failed")
|
|
||||||
throw InvalidTagException()
|
|
||||||
}
|
|
||||||
return plaintext.asUByteArray()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun cleanup() {
|
|
||||||
sodium.sodium_memzero(state.k, 32)
|
|
||||||
sodium.sodium_memzero(state.nonce, 12)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.blake2b
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.Initializer.sodium
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 14-Jul-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
actual class Blake2bDelegated actual constructor(key: UByteArray?, val hashLength: Int) : Blake2bMultipart {
|
|
||||||
|
|
||||||
val state = ByteArray(sodium.crypto_generichash_statebytes())
|
|
||||||
|
|
||||||
init {
|
|
||||||
sodium.crypto_generichash_init(state,key?.toByteArray() ?: byteArrayOf(), key?.size ?: 0, hashLength)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(data: UByteArray) {
|
|
||||||
sodium.crypto_generichash_update(state, data.toByteArray(), data.size.toLong())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun digest(): UByteArray {
|
|
||||||
val hashed = ByteArray(hashLength)
|
|
||||||
sodium.crypto_generichash_final(state, hashed, hashLength)
|
|
||||||
return hashed.asUByteArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
actual object Blake2bDelegatedStateless : Blake2b {
|
|
||||||
|
|
||||||
|
|
||||||
override fun digest(inputMessage: UByteArray, key: UByteArray, hashLength: Int): UByteArray {
|
|
||||||
val hashed = ByteArray(hashLength)
|
|
||||||
sodium.crypto_generichash(hashed, hashed.size, inputMessage.toByteArray(), inputMessage.size.toLong(), key.toByteArray(), key.size)
|
|
||||||
return hashed.asUByteArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.sha
|
|
||||||
|
|
||||||
import com.goterl.lazycode.lazysodium.interfaces.Hash
|
|
||||||
import com.ionspin.kotlin.crypto.Initializer.sodium
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 17-Jul-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
actual class Sha256Delegated actual constructor() : Sha256 {
|
|
||||||
|
|
||||||
val state = Hash.State256()
|
|
||||||
|
|
||||||
init {
|
|
||||||
sodium.crypto_hash_sha256_init(state)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(data: UByteArray) {
|
|
||||||
sodium.crypto_hash_sha256_update(state, data.toByteArray(), data.size.toLong())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun digest(): UByteArray {
|
|
||||||
val hashed = ByteArray(Sha256Properties.MAX_HASH_BYTES)
|
|
||||||
sodium.crypto_hash_sha256_final(state, hashed)
|
|
||||||
return hashed.asUByteArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
actual object Sha256StatelessDelegated : StatelessSha256 {
|
|
||||||
|
|
||||||
override fun digest(inputMessage: UByteArray): UByteArray {
|
|
||||||
val hashed = ByteArray(Sha256Properties.MAX_HASH_BYTES)
|
|
||||||
sodium.crypto_hash_sha256(hashed, inputMessage.toByteArray(), inputMessage.size.toLong())
|
|
||||||
return hashed.asUByteArray()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.sha
|
|
||||||
|
|
||||||
import com.goterl.lazycode.lazysodium.interfaces.Hash
|
|
||||||
import com.ionspin.kotlin.crypto.Initializer
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 17-Jul-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
actual class Sha512Delegated : Sha512Multipart {
|
|
||||||
|
|
||||||
val state = Hash.State512()
|
|
||||||
|
|
||||||
init {
|
|
||||||
Initializer.sodium.crypto_hash_sha512_init(state)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(data: UByteArray) {
|
|
||||||
Initializer.sodium.crypto_hash_sha512_update(state, data.toByteArray(), data.size.toLong())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun digest(): UByteArray {
|
|
||||||
val hashed = ByteArray(Sha512Properties.MAX_HASH_BYTES)
|
|
||||||
Initializer.sodium.crypto_hash_sha512_final(state, hashed)
|
|
||||||
return hashed.asUByteArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
actual object Sha512StatelessDelegated : Sha512 {
|
|
||||||
|
|
||||||
override fun digest(inputMessage: UByteArray): UByteArray {
|
|
||||||
val hashed = ByteArray(Sha512Properties.MAX_HASH_BYTES)
|
|
||||||
Initializer.sodium.crypto_hash_sha512(hashed, inputMessage.toByteArray(), inputMessage.size.toLong())
|
|
||||||
return hashed.asUByteArray()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto.util
|
|
||||||
|
|
||||||
import kotlin.coroutines.Continuation
|
|
||||||
import kotlin.coroutines.EmptyCoroutineContext
|
|
||||||
import kotlin.coroutines.startCoroutine
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 20-Jul-2019
|
|
||||||
*/
|
|
||||||
//actual fun testBlocking(block: suspend () -> Unit) {
|
|
||||||
// val continuation = Continuation<Unit>(EmptyCoroutineContext) {
|
|
||||||
// println("Done")
|
|
||||||
// }
|
|
||||||
// block.startCoroutine(continuation)
|
|
||||||
//
|
|
||||||
//}
|
|
@ -1,9 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.sha
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 07-Jun-2020
|
|
||||||
*/
|
|
||||||
import platform.posix.*
|
|
||||||
//import cin
|
|
@ -1,44 +0,0 @@
|
|||||||
//We'll handle SRNG through libsodium
|
|
||||||
///*
|
|
||||||
// * Copyright 2019 Ugljesa Jovanovic
|
|
||||||
// *
|
|
||||||
// * Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// * you may not use this file except in compliance with the License.
|
|
||||||
// * You may obtain a copy of the License at
|
|
||||||
// *
|
|
||||||
// * http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
// *
|
|
||||||
// * Unless required by applicable law or agreed to in writing, software
|
|
||||||
// * distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// * See the License for the specific language governing permissions and
|
|
||||||
// * limitations under the License.
|
|
||||||
// */
|
|
||||||
//
|
|
||||||
//package com.ionspin.kotlin.crypto
|
|
||||||
//
|
|
||||||
//import kotlinx.cinterop.*
|
|
||||||
//import platform.windows.*
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * Created by Ugljesa Jovanovic
|
|
||||||
// * ugljesa.jovanovic@ionspin.com
|
|
||||||
// * on 21-Sep-2019
|
|
||||||
// */
|
|
||||||
//actual object SRNG {
|
|
||||||
// private val advapi by lazy { LoadLibraryA("ADVAPI32.DLL")}
|
|
||||||
//
|
|
||||||
// private val advapiRandom by lazy {
|
|
||||||
// GetProcAddress(advapi, "SystemFunction036")?.reinterpret<CFunction<Function2<CPointer<ByteVar>, ULong, Int>>>() ?: error("Failed getting advapi random")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Suppress("EXPERIMENTAL_UNSIGNED_LITERALS")
|
|
||||||
// actual fun getRandomBytes(amount: Int): UByteArray {
|
|
||||||
// memScoped {
|
|
||||||
// val randArray = allocArray<ByteVar>(amount)
|
|
||||||
// val pointer = randArray.getPointer(this)
|
|
||||||
// val status = advapiRandom(pointer.reinterpret(), amount.convert())
|
|
||||||
// return UByteArray(amount) { pointer[it].toUByte() }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
@ -1,6 +0,0 @@
|
|||||||
headers = sodium.h
|
|
||||||
headerFilter = sodium.h sodium/**
|
|
||||||
#staticLibraries = libsodium.a
|
|
||||||
#libraryPaths = sodiumWrapper/lib
|
|
||||||
#compilerOpts = -I./sodiumWrapper/include
|
|
||||||
linkerOpts =
|
|
@ -1,30 +0,0 @@
|
|||||||
@file:Suppress("VARIABLE_IN_SINGLETON_WITHOUT_THREAD_LOCAL")
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import libsodium.sodium_init
|
|
||||||
import kotlin.native.concurrent.AtomicInt
|
|
||||||
|
|
||||||
actual object Initializer {
|
|
||||||
|
|
||||||
private var isPlatformInitialized : AtomicInt = AtomicInt(0)
|
|
||||||
|
|
||||||
actual suspend fun initialize() {
|
|
||||||
if (isPlatformInitialized.compareAndSet(0, 1)) {
|
|
||||||
sodium_init()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun initializeWithCallback(done: () -> Unit) {
|
|
||||||
if (isPlatformInitialized.compareAndSet(0, 1)) {
|
|
||||||
sodium_init()
|
|
||||||
}
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun isInitialized(): Boolean {
|
|
||||||
return isPlatformInitialized.value != 0
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import kotlinx.cinterop.*
|
|
||||||
import libsodium.randombytes_buf
|
|
||||||
import platform.posix.*
|
|
||||||
//import libsod
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 21-Sep-2019
|
|
||||||
*/
|
|
||||||
actual object SRNG {
|
|
||||||
@Suppress("EXPERIMENTAL_UNSIGNED_LITERALS")
|
|
||||||
actual fun getRandomBytes(amount: Int): UByteArray {
|
|
||||||
memScoped {
|
|
||||||
val array = allocArray<UByteVar>(amount)
|
|
||||||
randombytes_buf(array, amount.convert())
|
|
||||||
return UByteArray(amount) {
|
|
||||||
array[it]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,164 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.authenticated
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.bignum.integer.util.hexColumsPrint
|
|
||||||
import com.ionspin.kotlin.crypto.InvalidTagException
|
|
||||||
import com.ionspin.kotlin.crypto.util.toPtr
|
|
||||||
import kotlinx.cinterop.*
|
|
||||||
import libsodium.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 14-Jun-2020
|
|
||||||
*/
|
|
||||||
actual class XChaCha20Poly1305Delegated internal actual constructor() {
|
|
||||||
actual companion object {
|
|
||||||
actual fun encrypt(
|
|
||||||
key: UByteArray,
|
|
||||||
nonce: UByteArray,
|
|
||||||
message: UByteArray,
|
|
||||||
associatedData: UByteArray
|
|
||||||
): UByteArray {
|
|
||||||
val ciphertextLength = message.size + crypto_aead_xchacha20poly1305_IETF_ABYTES.toInt()
|
|
||||||
val ciphertext = UByteArray(ciphertextLength)
|
|
||||||
val ciphertextPinned = ciphertext.pin()
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_encrypt(
|
|
||||||
ciphertextPinned.toPtr(),
|
|
||||||
ulongArrayOf(ciphertextLength.convert()).toCValues(),
|
|
||||||
message.toCValues(),
|
|
||||||
message.size.convert(),
|
|
||||||
associatedData.toCValues(),
|
|
||||||
associatedData.size.convert(),
|
|
||||||
null,
|
|
||||||
nonce.toCValues(),
|
|
||||||
key.toCValues()
|
|
||||||
)
|
|
||||||
ciphertextPinned.unpin()
|
|
||||||
return ciphertext
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun decrypt(
|
|
||||||
key: UByteArray,
|
|
||||||
nonce: UByteArray,
|
|
||||||
ciphertext: UByteArray,
|
|
||||||
associatedData: UByteArray
|
|
||||||
): UByteArray {
|
|
||||||
val messageLength = ciphertext.size - crypto_aead_xchacha20poly1305_IETF_ABYTES.toInt()
|
|
||||||
val message = UByteArray(messageLength)
|
|
||||||
val messagePinned = message.pin()
|
|
||||||
crypto_aead_xchacha20poly1305_ietf_decrypt(
|
|
||||||
messagePinned.toPtr(),
|
|
||||||
ulongArrayOf(messageLength.convert()).toCValues(),
|
|
||||||
null,
|
|
||||||
ciphertext.toCValues(),
|
|
||||||
ciphertext.size.convert(),
|
|
||||||
associatedData.toCValues(),
|
|
||||||
associatedData.size.convert(),
|
|
||||||
nonce.toCValues(),
|
|
||||||
key.toCValues()
|
|
||||||
)
|
|
||||||
messagePinned.unpin()
|
|
||||||
return message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var state =
|
|
||||||
sodium_malloc(crypto_secretstream_xchacha20poly1305_state.size.convert())!!
|
|
||||||
.reinterpret<crypto_secretstream_xchacha20poly1305_state>()
|
|
||||||
.pointed
|
|
||||||
val header = UByteArray(crypto_secretstream_xchacha20poly1305_HEADERBYTES.toInt()) { 0U }
|
|
||||||
|
|
||||||
var isInitialized = false
|
|
||||||
var isEncryptor = false
|
|
||||||
|
|
||||||
actual internal constructor(
|
|
||||||
key: UByteArray,
|
|
||||||
testState: UByteArray,
|
|
||||||
testHeader: UByteArray,
|
|
||||||
isDecryptor: Boolean
|
|
||||||
) : this() {
|
|
||||||
val pointer = state.ptr.reinterpret<UByteVar>()
|
|
||||||
for (i in 0 until crypto_secretstream_xchacha20poly1305_state.size.toInt()) {
|
|
||||||
pointer[i] = testState[i]
|
|
||||||
}
|
|
||||||
println("state after setting-----------")
|
|
||||||
state.ptr.readBytes(crypto_secretstream_xchacha20poly1305_state.size.toInt()).asUByteArray().hexColumsPrint()
|
|
||||||
println("state after setting-----------")
|
|
||||||
println("header after setting-----------")
|
|
||||||
testHeader.copyInto(header)
|
|
||||||
header.hexColumsPrint()
|
|
||||||
println("header after setting-----------")
|
|
||||||
isInitialized = true
|
|
||||||
isEncryptor = !isDecryptor
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
actual fun initializeForEncryption(key: UByteArray) : UByteArray {
|
|
||||||
val pinnedHeader = header.pin()
|
|
||||||
crypto_secretstream_xchacha20poly1305_init_push(state.ptr, pinnedHeader.toPtr(), key.toCValues())
|
|
||||||
println("state-----------")
|
|
||||||
state.ptr.readBytes(crypto_secretstream_xchacha20poly1305_state.size.toInt()).asUByteArray().hexColumsPrint()
|
|
||||||
println("state-----------")
|
|
||||||
println("--------header-----------")
|
|
||||||
header.hexColumsPrint()
|
|
||||||
println("--------header-----------")
|
|
||||||
pinnedHeader.unpin()
|
|
||||||
return header
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun initializeForDecryption(key: UByteArray, header: UByteArray) {
|
|
||||||
crypto_secretstream_xchacha20poly1305_init_pull(state.ptr, header.toCValues(), key.toCValues())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
actual fun encrypt(data: UByteArray, associatedData: UByteArray): UByteArray {
|
|
||||||
val ciphertextWithTag = UByteArray(data.size + crypto_secretstream_xchacha20poly1305_ABYTES.toInt())
|
|
||||||
val ciphertextWithTagPinned = ciphertextWithTag.pin()
|
|
||||||
crypto_secretstream_xchacha20poly1305_push(
|
|
||||||
state.ptr,
|
|
||||||
ciphertextWithTagPinned.toPtr(),
|
|
||||||
null,
|
|
||||||
data.toCValues(),
|
|
||||||
data.size.convert(),
|
|
||||||
associatedData.toCValues(),
|
|
||||||
associatedData.size.convert(),
|
|
||||||
0U,
|
|
||||||
)
|
|
||||||
println("Encrypt partial")
|
|
||||||
ciphertextWithTag.hexColumsPrint()
|
|
||||||
println("Encrypt partial end")
|
|
||||||
ciphertextWithTagPinned.unpin()
|
|
||||||
return ciphertextWithTag
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun decrypt(data: UByteArray, associatedData: UByteArray): UByteArray {
|
|
||||||
val plaintext = UByteArray(data.size - crypto_secretstream_xchacha20poly1305_ABYTES.toInt())
|
|
||||||
val plaintextPinned = plaintext.pin()
|
|
||||||
val validTag = crypto_secretstream_xchacha20poly1305_pull(
|
|
||||||
state.ptr,
|
|
||||||
plaintextPinned.toPtr(),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
data.toCValues(),
|
|
||||||
data.size.convert(),
|
|
||||||
associatedData.toCValues(),
|
|
||||||
associatedData.size.convert()
|
|
||||||
)
|
|
||||||
plaintextPinned.unpin()
|
|
||||||
println("tag: $validTag")
|
|
||||||
if (validTag != 0) {
|
|
||||||
println("Tag validation failed")
|
|
||||||
throw InvalidTagException()
|
|
||||||
}
|
|
||||||
return plaintext
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun cleanup() {
|
|
||||||
sodium_free(state.ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.blake2b
|
|
||||||
import com.ionspin.kotlin.crypto.util.toHexString
|
|
||||||
import com.ionspin.kotlin.crypto.util.toPtr
|
|
||||||
import kotlinx.cinterop.*
|
|
||||||
import libsodium.*
|
|
||||||
import platform.posix.free
|
|
||||||
import platform.posix.malloc
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 14-Jul-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
actual class Blake2bDelegated actual constructor(key: UByteArray?, hashLength: Int) : Blake2bMultipart {
|
|
||||||
override val MAX_HASH_BYTES: Int = 64
|
|
||||||
|
|
||||||
val requestedHashLength : Int
|
|
||||||
val state : crypto_generichash_state
|
|
||||||
init {
|
|
||||||
requestedHashLength = hashLength
|
|
||||||
val allocated = malloc(crypto_generichash_state.size.convert())!!
|
|
||||||
state = allocated.reinterpret<crypto_generichash_state>().pointed
|
|
||||||
crypto_generichash_init(state.ptr, key?.run { this.toCValues() }, key?.size?.convert() ?: 0UL.convert(), hashLength.convert())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(data: UByteArray) {
|
|
||||||
crypto_generichash_update(state.ptr, data.toCValues(), data.size.convert())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun digest(): UByteArray {
|
|
||||||
val hashResult = UByteArray(requestedHashLength)
|
|
||||||
val hashResultPinned = hashResult.pin()
|
|
||||||
crypto_generichash_final(state.ptr, hashResultPinned.toPtr(), requestedHashLength.convert())
|
|
||||||
free(state.ptr)
|
|
||||||
return hashResult
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
|
|
||||||
actual object Blake2bDelegatedStateless : Blake2b {
|
|
||||||
|
|
||||||
override fun digest(inputMessage: UByteArray, key: UByteArray, hashLength: Int): UByteArray {
|
|
||||||
val hashResult = UByteArray(MAX_HASH_BYTES)
|
|
||||||
val hashResultPinned = hashResult.pin()
|
|
||||||
crypto_generichash(
|
|
||||||
hashResultPinned.toPtr(),
|
|
||||||
hashLength.convert(),
|
|
||||||
inputMessage.toCValues(),
|
|
||||||
inputMessage.size.convert(),
|
|
||||||
key.toCValues(),
|
|
||||||
key.size.convert()
|
|
||||||
)
|
|
||||||
hashResultPinned.unpin()
|
|
||||||
return hashResult
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.sha
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bDelegatedStateless
|
|
||||||
import com.ionspin.kotlin.crypto.util.toPtr
|
|
||||||
import kotlinx.cinterop.*
|
|
||||||
import libsodium.*
|
|
||||||
import platform.posix.free
|
|
||||||
import platform.posix.malloc
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 17-Jul-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
actual class Sha256Delegated : Sha256 {
|
|
||||||
|
|
||||||
val state : crypto_hash_sha256_state
|
|
||||||
|
|
||||||
init {
|
|
||||||
val allocated = sodium_malloc(crypto_hash_sha256_state.size.convert())!!
|
|
||||||
state = allocated.reinterpret<crypto_hash_sha256_state>().pointed
|
|
||||||
crypto_hash_sha256_init(state.ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(data: UByteArray) {
|
|
||||||
crypto_hash_sha256_update(state.ptr, data.toCValues(), data.size.convert())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override fun digest(): UByteArray {
|
|
||||||
val hashResult = UByteArray(Sha256Properties.MAX_HASH_BYTES)
|
|
||||||
val hashResultPinned = hashResult.pin()
|
|
||||||
crypto_hash_sha256_final(state.ptr, hashResultPinned.toPtr())
|
|
||||||
sodium_free(state.ptr)
|
|
||||||
return hashResult
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
actual object Sha256StatelessDelegated : StatelessSha256 {
|
|
||||||
|
|
||||||
override fun digest(inputMessage: UByteArray): UByteArray {
|
|
||||||
val hashResult = UByteArray(MAX_HASH_BYTES)
|
|
||||||
val hashResultPinned = hashResult.pin()
|
|
||||||
crypto_hash_sha256(hashResultPinned.toPtr(), inputMessage.toCValues(), inputMessage.size.convert())
|
|
||||||
hashResultPinned.unpin()
|
|
||||||
return hashResult
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.hash.sha
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.util.toPtr
|
|
||||||
import kotlinx.cinterop.*
|
|
||||||
import libsodium.*
|
|
||||||
import platform.posix.free
|
|
||||||
import platform.posix.malloc
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 17-Jul-2019
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
actual class Sha512Delegated : Sha512Multipart {
|
|
||||||
val state : crypto_hash_sha512_state
|
|
||||||
|
|
||||||
init {
|
|
||||||
val allocated = malloc(crypto_hash_sha512_state.size.convert())!!
|
|
||||||
state = allocated.reinterpret<crypto_hash_sha512_state>().pointed
|
|
||||||
crypto_hash_sha512_init(state.ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(data: UByteArray) {
|
|
||||||
crypto_hash_sha512_update(state.ptr, data.toCValues(), data.size.convert())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override fun digest(): UByteArray {
|
|
||||||
val hashResult = UByteArray(Sha512Properties.MAX_HASH_BYTES)
|
|
||||||
val hashResultPinned = hashResult.pin()
|
|
||||||
crypto_hash_sha512_final(state.ptr, hashResultPinned.toPtr())
|
|
||||||
free(state.ptr)
|
|
||||||
return hashResult
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
actual object Sha512StatelessDelegated : Sha512 {
|
|
||||||
|
|
||||||
override fun digest(inputMessage: UByteArray): UByteArray {
|
|
||||||
val hashResult = UByteArray(Sha512StatelessDelegated.MAX_HASH_BYTES)
|
|
||||||
val hashResultPinned = hashResult.pin()
|
|
||||||
crypto_hash_sha512(hashResultPinned.toPtr(), inputMessage.toCValues(), inputMessage.size.convert())
|
|
||||||
hashResultPinned.unpin()
|
|
||||||
return hashResult
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto.util
|
|
||||||
|
|
||||||
import kotlinx.cinterop.CPointer
|
|
||||||
import kotlinx.cinterop.Pinned
|
|
||||||
import kotlinx.cinterop.UByteVar
|
|
||||||
import kotlinx.cinterop.addressOf
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 27-Aug-2020
|
|
||||||
*/
|
|
||||||
fun Pinned<UByteArray>.toPtr() : CPointer<UByteVar> = addressOf(0)
|
|
@ -1,77 +0,0 @@
|
|||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
|
||||||
import com.ionspin.kotlin.crypto.util.toHexString
|
|
||||||
import com.ionspin.kotlin.crypto.util.toPtr
|
|
||||||
import kotlinx.cinterop.*
|
|
||||||
import libsodium.*
|
|
||||||
import platform.posix.free
|
|
||||||
import platform.posix.malloc
|
|
||||||
import kotlin.test.Ignore
|
|
||||||
import kotlin.test.Test
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 13-Jul-2020
|
|
||||||
*/
|
|
||||||
class HelperTest {
|
|
||||||
@Ignore //Just used for debugging pure implementation
|
|
||||||
@Test
|
|
||||||
fun longSha256() {
|
|
||||||
for (target in 0L until 10L) {
|
|
||||||
generateForRounds256(target)
|
|
||||||
}
|
|
||||||
for (target in 0L until 16_777_216L step 1_000_000L) {
|
|
||||||
generateForRounds256(target)
|
|
||||||
}
|
|
||||||
generateForRounds256(16_777_216L)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun generateForRounds256(target: Long) {
|
|
||||||
val updateValue =
|
|
||||||
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno".encodeToUByteArray().toCValues()
|
|
||||||
val state = malloc(crypto_hash_sha256_state.size.convert())!!
|
|
||||||
.reinterpret<crypto_hash_sha256_state>()
|
|
||||||
|
|
||||||
crypto_hash_sha256_init(state)
|
|
||||||
for (i in 0 until target) {
|
|
||||||
crypto_hash_sha256_update(state, updateValue, updateValue.size.convert())
|
|
||||||
}
|
|
||||||
val result = UByteArray(32)
|
|
||||||
val resultPinned = result.pin()
|
|
||||||
crypto_hash_sha256_final(state, resultPinned.toPtr())
|
|
||||||
println("$target to \"${result.toHexString()}\",")
|
|
||||||
free(state)
|
|
||||||
}
|
|
||||||
@Ignore //Just used for debugging pure implementation
|
|
||||||
@Test
|
|
||||||
fun longSha512() {
|
|
||||||
|
|
||||||
for (target in 0L until 10L) {
|
|
||||||
generateForRounds512(target)
|
|
||||||
}
|
|
||||||
for (target in 0L until 16_777_216L step 1_000_000L) {
|
|
||||||
generateForRounds512(target)
|
|
||||||
}
|
|
||||||
generateForRounds512(16_777_216L)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun generateForRounds512(target: Long) {
|
|
||||||
println("Wut")
|
|
||||||
val updateValue =
|
|
||||||
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno".encodeToUByteArray().toCValues()
|
|
||||||
val state = malloc(crypto_hash_sha512_state.size.convert())!!
|
|
||||||
.reinterpret<crypto_hash_sha512_state>()
|
|
||||||
|
|
||||||
crypto_hash_sha512_init(state)
|
|
||||||
for (i in 0 until target) {
|
|
||||||
crypto_hash_sha512_update(state, updateValue, updateValue.size.convert())
|
|
||||||
}
|
|
||||||
val result = UByteArray(32)
|
|
||||||
val resultPinned = result.pin()
|
|
||||||
crypto_hash_sha512_final(state, resultPinned.toPtr())
|
|
||||||
println("$target to \"${result.toHexString()}\",")
|
|
||||||
free(state)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//package com.ionspin.kotlin.crypto.util
|
|
||||||
//
|
|
||||||
//import kotlinx.coroutines.CoroutineScope
|
|
||||||
//import kotlinx.coroutines.runBlocking
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * Created by Ugljesa Jovanovic
|
|
||||||
// * ugljesa.jovanovic@ionspin.com
|
|
||||||
// * on 20-Jul-2019
|
|
||||||
// */
|
|
||||||
//actual fun testBlocking(block: suspend () -> Unit) = runBlocking { block() }
|
|
@ -20,6 +20,8 @@
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest
|
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest
|
||||||
|
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
|
||||||
|
import org.jetbrains.dokka.Platform
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin(PluginsDeps.multiplatform)
|
kotlin(PluginsDeps.multiplatform)
|
||||||
@ -593,18 +595,43 @@ tasks {
|
|||||||
dokkaJavadoc {
|
dokkaJavadoc {
|
||||||
println("Dokka !")
|
println("Dokka !")
|
||||||
dokkaSourceSets {
|
dokkaSourceSets {
|
||||||
create("commonMain") {
|
named("commonMain") {
|
||||||
displayName = "common"
|
displayName.set("common")
|
||||||
platform = "common"
|
platform.set(Platform.common)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dokkaHtml {
|
||||||
|
println("Dokka Html!")
|
||||||
|
dokkaSourceSets {
|
||||||
|
named("commonMain") {
|
||||||
|
// displayName.set("common")
|
||||||
|
// platform.set(Platform.common)
|
||||||
|
moduleDisplayName.set("Kotlin Multiplatform Libsodium Bindings")
|
||||||
|
includes.from(
|
||||||
|
"src/commonMain/kotlin/com.ionspin.kotlin.crypto/aead/Aead.md",
|
||||||
|
"src/commonMain/kotlin/com.ionspin.kotlin.crypto/auth/Auth.md",
|
||||||
|
"src/commonMain/kotlin/com.ionspin.kotlin.crypto/box/Box.md",
|
||||||
|
"src/commonMain/kotlin/com.ionspin.kotlin.crypto/CryptoModule.md")
|
||||||
|
displayName.set("Kotlin multiplatform")
|
||||||
|
}
|
||||||
|
configureEach {
|
||||||
|
if (name != "commonMain") {
|
||||||
|
suppress.set(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (getHostOsName() == "linux" && getHostArchitecture() == "x86-64") {
|
if (getHostOsName() == "linux" && getHostArchitecture() == "x86-64") {
|
||||||
val jvmTest by getting(Test::class) {
|
val jvmTest by getting(Test::class) {
|
||||||
testLogging {
|
testLogging {
|
||||||
events("PASSED", "FAILED", "SKIPPED")
|
events("PASSED", "FAILED", "SKIPPED")
|
||||||
|
exceptionFormat = TestExceptionFormat.FULL
|
||||||
|
showStandardStreams = true
|
||||||
|
showStackTraces = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,14 +639,18 @@ tasks {
|
|||||||
|
|
||||||
testLogging {
|
testLogging {
|
||||||
events("PASSED", "FAILED", "SKIPPED")
|
events("PASSED", "FAILED", "SKIPPED")
|
||||||
|
exceptionFormat = TestExceptionFormat.FULL
|
||||||
showStandardStreams = true
|
showStandardStreams = true
|
||||||
|
showStackTraces = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val jsNodeTest by getting(KotlinJsTest::class) {
|
val jsNodeTest by getting(KotlinJsTest::class) {
|
||||||
testLogging {
|
testLogging {
|
||||||
events("PASSED", "FAILED", "SKIPPED")
|
events("PASSED", "FAILED", "SKIPPED")
|
||||||
// showStandardStreams = true
|
exceptionFormat = TestExceptionFormat.FULL
|
||||||
|
showStandardStreams = true
|
||||||
|
showStackTraces = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
# Module Kotlin Multiplatform Libsodium Bindings
|
||||||
|
|
||||||
|
### What
|
||||||
|
Kotlin Multiplatform Libsodium Bindings is a library providing kotlin idiomatic API to libsodium implementations on various platforms
|
||||||
|
|
||||||
|
### Why
|
||||||
|
To provide easy to use cryptographic library, based on a well-known and audited libsodium library. T
|
||||||
|
### How
|
||||||
|
By using built from source libsodium to provide native implementations, LazySodium (JNA wrapper around libsodium) to provide
|
||||||
|
JVM and Android implementations and libsodium.js to provide node and browser implementation
|
@ -0,0 +1,28 @@
|
|||||||
|
# Package com.ionspin.kotlin.crypto.aead
|
||||||
|
|
||||||
|
## Authenticated encryption with associated data
|
||||||
|
|
||||||
|
This is a form of symmetric encryption, that assures both confidentiality and authenticity of the data to be encrypted as well
|
||||||
|
as associated data that will not be encrypted.
|
||||||
|
|
||||||
|
In general, it works like this:
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
- Message to encrypt and authenticate
|
||||||
|
- Key to use for encryption
|
||||||
|
- **Unique** nonce
|
||||||
|
- Additional data that is not encrypted but also authenticated
|
||||||
|
|
||||||
|
Simplified encryption algorithm:
|
||||||
|
1. Encrypt a message with key and nonce
|
||||||
|
1. Apply MAC algorithm to encrypted message + unencrypted associated data to generate authentication data (tag)
|
||||||
|
1. Send the encrypted data + associated data + authentication data + nonce
|
||||||
|
|
||||||
|
Simplified decryption algorithm:
|
||||||
|
1. Apply MAC algorithm to encrypted message + unencrypted associated data to generate authentication data
|
||||||
|
1. If the generated authenticated data, and the received authentication data match, proceed, otherwise sound the alarm and stop.
|
||||||
|
1. Decrypt the encrypted data
|
||||||
|
1. Return the decrypted data and associated data to the user
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -22,13 +22,52 @@ val crypto_aead_chacha20poly1305_KEYBYTES = 32
|
|||||||
val crypto_aead_chacha20poly1305_NPUBBYTES = 8
|
val crypto_aead_chacha20poly1305_NPUBBYTES = 8
|
||||||
val crypto_aead_chacha20poly1305_ABYTES = 16
|
val crypto_aead_chacha20poly1305_ABYTES = 16
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data class wrapping returned encrypted data and and tag from aead encrypt functions.
|
||||||
|
*/
|
||||||
data class AeadEncryptedDataAndTag(val data: UByteArray, val tag: UByteArray)
|
data class AeadEncryptedDataAndTag(val data: UByteArray, val tag: UByteArray)
|
||||||
|
|
||||||
class AeadCorrupedOrTamperedDataException() : RuntimeException("MAC validation failed. Data is corrupted or tampered with.")
|
/**
|
||||||
|
* An exception thrown when tag generated from received data and key doesn't match the received tag
|
||||||
|
*/
|
||||||
|
class AeadCorrupedOrTamperedDataException() :
|
||||||
|
RuntimeException("Tag (authentication data) validation failed. Data is corrupted or tampered with.")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a form of symmetric encryption, that assures both confidentiality and authenticity of the data to be encrypted as well
|
||||||
|
as associated data that will not be encrypted.
|
||||||
|
*
|
||||||
|
* Offered here are three implementations of (x)ChaCha20-Poly1305 construction:
|
||||||
|
* - ChaCha20Poly1305 - uses 64bit nonce, safe to encrypt
|
||||||
|
* - ChaCha20Poly1305-IETF - uses 96bit nonce (standardised by [RFC8439](https://tools.ietf.org/html/rfc8439)
|
||||||
|
* - XChaCha20Poly1305 - uses 192bit nonce - recommended choice
|
||||||
|
*
|
||||||
|
* The only difference is the size of the nonce, and how is the nonce used.
|
||||||
|
*
|
||||||
|
* (x)ChaCha20 is a streaming cipher develop by Daniel J. Bernstein. He is also the author of Poly1305 a fast Message
|
||||||
|
* Authentication Code system
|
||||||
|
*
|
||||||
|
* Libsodium offers two additional variants for each of the aforementioned variants:
|
||||||
|
* - Combined
|
||||||
|
* - Detached
|
||||||
|
*
|
||||||
|
* Combined mode returns encrypted data and tag as one UByteArray, while detached mode returns them as separate UByteArrays.
|
||||||
|
* To be kotlin idiomatic we are returning detached tag and encrypted data inside a wrapper data class [AeadEncryptedDataAndTag]
|
||||||
|
*
|
||||||
|
* Also provided are key generation convenience functions for each variant. (Which is in practice the same, since the keys
|
||||||
|
* same length for each variant)
|
||||||
|
*/
|
||||||
expect object AuthenticatedEncryptionWithAssociatedData {
|
expect object AuthenticatedEncryptionWithAssociatedData {
|
||||||
// X - Ietf
|
// X - Ietf
|
||||||
|
/**
|
||||||
|
* Encrypt the message and return encrypted data and tag using xChaChaPoly1305 (192 bit nonce)
|
||||||
|
*
|
||||||
|
* @param message message to encrypt
|
||||||
|
* @param associatedData associated data the won't be encrypted, but will be authenticated
|
||||||
|
* @param nonce a **unique** nonce
|
||||||
|
* @param key secret key
|
||||||
|
* @return encrypted data and tag (in that order)
|
||||||
|
*/
|
||||||
fun xChaCha20Poly1305IetfEncrypt(
|
fun xChaCha20Poly1305IetfEncrypt(
|
||||||
message: UByteArray,
|
message: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
@ -36,13 +75,34 @@ expect object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray
|
): UByteArray
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if authentication data (tag) is correct, then decrypt the message and return decrypted data.
|
||||||
|
* Using xChaChaPoly1305 (192 bit nonce)
|
||||||
|
*
|
||||||
|
* @param ciphertextAndTag message to decrypt
|
||||||
|
* @param associatedData associated data the won't be encrypted, but will be authenticated
|
||||||
|
* @param nonce a nonce used to encrypt the message
|
||||||
|
* @param key secret key
|
||||||
|
* @return decrypted data
|
||||||
|
* @throws AeadCorrupedOrTamperedDataException if authentication data (tag) cannot be verified
|
||||||
|
*/
|
||||||
fun xChaCha20Poly1305IetfDecrypt(
|
fun xChaCha20Poly1305IetfDecrypt(
|
||||||
ciphertext: UByteArray,
|
ciphertextAndTag: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
nonce: UByteArray,
|
nonce: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray
|
): UByteArray
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt the message and return encrypted data and tag using xChaChaPoly1305 (192 bit nonce) as
|
||||||
|
* separate arrays (but wrapped inside [AeadEncryptedDataAndTag])
|
||||||
|
*
|
||||||
|
* @param message message to encrypt
|
||||||
|
* @param associatedData associated data the won't be encrypted, but will be authenticated
|
||||||
|
* @param nonce a **unique** nonce
|
||||||
|
* @param key secret key
|
||||||
|
* @return encrypted data and tag wrapped inside [AeadEncryptedDataAndTag] data class instance
|
||||||
|
*/
|
||||||
fun xChaCha20Poly1305IetfEncryptDetached(
|
fun xChaCha20Poly1305IetfEncryptDetached(
|
||||||
message: UByteArray,
|
message: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
@ -50,6 +110,18 @@ expect object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): AeadEncryptedDataAndTag
|
): AeadEncryptedDataAndTag
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if authentication data (tag) is correct, then decrypt the message and return decrypted data.
|
||||||
|
* Using xChaChaPoly1305 (192 bit nonce)
|
||||||
|
*
|
||||||
|
* @param ciphertext message to decrypt
|
||||||
|
* @param tag authenticatoin data (tag)
|
||||||
|
* @param associatedData associated data the won't be encrypted, but will be authenticated
|
||||||
|
* @param nonce a nonce used to encrypt the message
|
||||||
|
* @param key secret key
|
||||||
|
* @return decrypted data
|
||||||
|
* @throws AeadCorrupedOrTamperedDataException if authentication data (tag) cannot be verified
|
||||||
|
*/
|
||||||
fun xChaCha20Poly1305IetfDecryptDetached(
|
fun xChaCha20Poly1305IetfDecryptDetached(
|
||||||
ciphertext: UByteArray,
|
ciphertext: UByteArray,
|
||||||
tag: UByteArray,
|
tag: UByteArray,
|
||||||
@ -59,21 +131,48 @@ expect object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
): UByteArray
|
): UByteArray
|
||||||
|
|
||||||
// Ietf
|
// Ietf
|
||||||
|
/**
|
||||||
|
* Encrypt the message and return encrypted data and tag using ChaChaPoly1305-IETF (96 bit nonce)
|
||||||
|
*
|
||||||
|
* @param message message to encrypt
|
||||||
|
* @param associatedData associated data the won't be encrypted, but will be authenticated
|
||||||
|
* @param nonce a **unique** nonce
|
||||||
|
* @param key secret key
|
||||||
|
* @return encrypted data and tag (in that order)
|
||||||
|
*/
|
||||||
fun chaCha20Poly1305IetfEncrypt(
|
fun chaCha20Poly1305IetfEncrypt(
|
||||||
message: UByteArray,
|
message: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
nonce: UByteArray,
|
nonce: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray
|
): UByteArray
|
||||||
|
/**
|
||||||
|
* Check if authentication data (tag) is correct, then decrypt the message and return decrypted data.
|
||||||
|
* Using ChaChaPoly1305-IETF (96 bit nonce)
|
||||||
|
*
|
||||||
|
* @param ciphertextAndTag message to decrypt
|
||||||
|
* @param associatedData associated data the won't be encrypted, but will be authenticated
|
||||||
|
* @param nonce a nonce used to encrypt the message
|
||||||
|
* @param key secret key
|
||||||
|
* @return decrypted data
|
||||||
|
* @throws AeadCorrupedOrTamperedDataException if authentication data (tag) cannot be verified
|
||||||
|
*/
|
||||||
fun chaCha20Poly1305IetfDecrypt(
|
fun chaCha20Poly1305IetfDecrypt(
|
||||||
ciphertext: UByteArray,
|
ciphertextAndTag: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
nonce: UByteArray,
|
nonce: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray
|
): UByteArray
|
||||||
|
/**
|
||||||
|
* Encrypt the message and return encrypted data and tag using ChaChaPoly1305-IETF (96 bit nonce) as
|
||||||
|
* separate arrays (but wrapped inside [AeadEncryptedDataAndTag])
|
||||||
|
*
|
||||||
|
* @param message message to encrypt
|
||||||
|
* @param associatedData associated data the won't be encrypted, but will be authenticated
|
||||||
|
* @param nonce a **unique** nonce
|
||||||
|
* @param key secret key
|
||||||
|
* @return encrypted data and tag wrapped inside [AeadEncryptedDataAndTag] data class instance
|
||||||
|
*/
|
||||||
fun chaCha20Poly1305IetfEncryptDetached(
|
fun chaCha20Poly1305IetfEncryptDetached(
|
||||||
message: UByteArray,
|
message: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
@ -81,6 +180,18 @@ expect object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): AeadEncryptedDataAndTag
|
): AeadEncryptedDataAndTag
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if authentication data (tag) is correct, then decrypt the message and return decrypted data.
|
||||||
|
* Using xChaChaPoly1305 (96 bit nonce)
|
||||||
|
*
|
||||||
|
* @param ciphertext message to decrypt
|
||||||
|
* @param tag authenticatoin data (tag)
|
||||||
|
* @param associatedData associated data the won't be encrypted, but will be authenticated
|
||||||
|
* @param nonce a nonce used to encrypt the message
|
||||||
|
* @param key secret key
|
||||||
|
* @return decrypted data
|
||||||
|
* @throws AeadCorrupedOrTamperedDataException if authentication data (tag) cannot be verified
|
||||||
|
*/
|
||||||
fun chaCha20Poly1305IetfDecryptDetached(
|
fun chaCha20Poly1305IetfDecryptDetached(
|
||||||
ciphertext: UByteArray,
|
ciphertext: UByteArray,
|
||||||
tag: UByteArray,
|
tag: UByteArray,
|
||||||
@ -90,28 +201,66 @@ expect object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
): UByteArray
|
): UByteArray
|
||||||
|
|
||||||
// Original chacha20poly1305
|
// Original chacha20poly1305
|
||||||
|
/**
|
||||||
|
* Encrypt the message and return encrypted data and tag using ChaChaPoly1305 (64 bit nonce)
|
||||||
|
*
|
||||||
|
* @param message message to encrypt
|
||||||
|
* @param associatedData associated data the won't be encrypted, but will be authenticated
|
||||||
|
* @param nonce a **unique** nonce
|
||||||
|
* @param key secret key
|
||||||
|
* @return encrypted data and tag (in that order)
|
||||||
|
*/
|
||||||
fun chaCha20Poly1305Encrypt(
|
fun chaCha20Poly1305Encrypt(
|
||||||
message: UByteArray,
|
message: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
nonce: UByteArray,
|
nonce: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray
|
): UByteArray
|
||||||
|
/**
|
||||||
|
* Check if authentication data (tag) is correct, then decrypt the message and return decrypted data.
|
||||||
|
* Using ChaChaPoly1305 (64 bit nonce)
|
||||||
|
*
|
||||||
|
* @param ciphertextAndTag message to decrypt
|
||||||
|
* @param associatedData associated data the won't be encrypted, but will be authenticated
|
||||||
|
* @param nonce a nonce used to encrypt the message
|
||||||
|
* @param key secret key
|
||||||
|
* @return decrypted data
|
||||||
|
* @throws AeadCorrupedOrTamperedDataException if authentication data (tag) cannot be verified
|
||||||
|
*/
|
||||||
fun chaCha20Poly1305Decrypt(
|
fun chaCha20Poly1305Decrypt(
|
||||||
ciphertext: UByteArray,
|
ciphertextAndTag: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
nonce: UByteArray,
|
nonce: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray
|
): UByteArray
|
||||||
|
/**
|
||||||
|
* Encrypt the message and return encrypted data and tag using ChaChaPoly1305 (64 bit nonce) as
|
||||||
|
* separate arrays (but wrapped inside [AeadEncryptedDataAndTag])
|
||||||
|
*
|
||||||
|
* @param message message to encrypt
|
||||||
|
* @param associatedData associated data the won't be encrypted, but will be authenticated
|
||||||
|
* @param nonce a **unique** nonce
|
||||||
|
* @param key secret key
|
||||||
|
* @return encrypted data and tag wrapped inside [AeadEncryptedDataAndTag] data class instance
|
||||||
|
*/
|
||||||
fun chaCha20Poly1305EncryptDetached(
|
fun chaCha20Poly1305EncryptDetached(
|
||||||
message: UByteArray,
|
message: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
nonce: UByteArray,
|
nonce: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
): AeadEncryptedDataAndTag
|
): AeadEncryptedDataAndTag
|
||||||
|
/**
|
||||||
|
* Check if authentication data (tag) is correct, then decrypt the message and return decrypted data.
|
||||||
|
* Using xChaChaPoly1305 (64 bit nonce)
|
||||||
|
*
|
||||||
|
* @param ciphertext message to decrypt
|
||||||
|
* @param tag authenticatoin data (tag)
|
||||||
|
* @param associatedData associated data the won't be encrypted, but will be authenticated
|
||||||
|
* @param nonce a nonce used to encrypt the message
|
||||||
|
* @param key secret key
|
||||||
|
* @return decrypted data
|
||||||
|
* @throws AeadCorrupedOrTamperedDataException if authentication data (tag) cannot be verified
|
||||||
|
*/
|
||||||
fun chaCha20Poly1305DecryptDetached(
|
fun chaCha20Poly1305DecryptDetached(
|
||||||
ciphertext: UByteArray,
|
ciphertext: UByteArray,
|
||||||
tag: UByteArray,
|
tag: UByteArray,
|
||||||
@ -120,9 +269,20 @@ expect object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray
|
): UByteArray
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random 32byte key for use with xChaCha20Poly1305
|
||||||
|
* @return secret key
|
||||||
|
*/
|
||||||
fun xChaCha20Poly1305IetfKeygen(): UByteArray
|
fun xChaCha20Poly1305IetfKeygen(): UByteArray
|
||||||
|
/**
|
||||||
|
* Generate a random 32 byte key for use with ChaCha20Poly1305-IETF
|
||||||
|
* @return secret key
|
||||||
|
*/
|
||||||
fun chaCha20Poly1305IetfKeygen(): UByteArray
|
fun chaCha20Poly1305IetfKeygen(): UByteArray
|
||||||
|
/**
|
||||||
|
* Generate a random 32 byte key for use with ChaCha20Poly1305
|
||||||
|
* @return secret key
|
||||||
|
*/
|
||||||
fun chaCha20Poly1305Keygen(): UByteArray
|
fun chaCha20Poly1305Keygen(): UByteArray
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,18 +19,60 @@ val crypto_auth_hmacsha256_BYTES = 32
|
|||||||
val crypto_auth_hmacsha512_KEYBYTES = 32
|
val crypto_auth_hmacsha512_KEYBYTES = 32
|
||||||
val crypto_auth_hmacsha512_BYTES = 64
|
val crypto_auth_hmacsha512_BYTES = 64
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication is a process of generating authentication data (tag) for a certain message. Its purpose is to assure
|
||||||
|
* that the data hasn't been corrupted or tampered with during the transport.
|
||||||
|
*
|
||||||
|
* We support 3 variants:
|
||||||
|
* - without suffix - HMAC-SHA512-256 (HMAC SHA512 with just the first 256 bits used)
|
||||||
|
* - *HmacSha256 - HMAC-SHA256
|
||||||
|
* - *HmacSha512 - HMAC-SHA512
|
||||||
|
*
|
||||||
|
* Each variant supports three operations:
|
||||||
|
* - keygen - generate appropriate key for MAC function
|
||||||
|
* - auth - generate the authentication data (tag/mac)
|
||||||
|
* - verify - verify that the authenticatoin data (tag/mac) is correct
|
||||||
|
*/
|
||||||
expect object Auth {
|
expect object Auth {
|
||||||
|
/**
|
||||||
|
* Generate a secret key, meant to be used with auth function.
|
||||||
|
*/
|
||||||
fun authKeygen() : UByteArray
|
fun authKeygen() : UByteArray
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a HMAC-SHA512-256 authentication data - Message Authentication Code - tag
|
||||||
|
*/
|
||||||
fun auth(message: UByteArray, key: UByteArray) : UByteArray
|
fun auth(message: UByteArray, key: UByteArray) : UByteArray
|
||||||
fun authVerify(mac: UByteArray, message: UByteArray, key: UByteArray) : Boolean
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that given message, secret key and tag, a newly calculated tag matches the received HMAC-SHA512-256 tag.
|
||||||
|
*/
|
||||||
|
fun authVerify(tag: UByteArray, message: UByteArray, key: UByteArray) : Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a secret key, meant to be used with auth function.
|
||||||
|
*/
|
||||||
fun authHmacSha256Keygen() : UByteArray
|
fun authHmacSha256Keygen() : UByteArray
|
||||||
|
/**
|
||||||
|
* Generate a HMAC-SHA256 authentication data - Message Authentication Code - tag
|
||||||
|
*/
|
||||||
fun authHmacSha256(message: UByteArray, key: UByteArray) : UByteArray
|
fun authHmacSha256(message: UByteArray, key: UByteArray) : UByteArray
|
||||||
fun authHmacSha256Verify(mac: UByteArray, message: UByteArray, key: UByteArray) : Boolean
|
/**
|
||||||
|
* Verify that given message, secret key and tag, a newly calculated tag matches the received HMAC-SHA256 tag.
|
||||||
|
*/
|
||||||
|
fun authHmacSha256Verify(tag: UByteArray, message: UByteArray, key: UByteArray) : Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a secret key, meant to be used with auth function.
|
||||||
|
*/
|
||||||
fun authHmacSha512Keygen() : UByteArray
|
fun authHmacSha512Keygen() : UByteArray
|
||||||
|
/**
|
||||||
|
* Generate a HMAC-SHA512 authentication data - Message Authentication Code - tag
|
||||||
|
*/
|
||||||
fun authHmacSha512(message: UByteArray, key: UByteArray) : UByteArray
|
fun authHmacSha512(message: UByteArray, key: UByteArray) : UByteArray
|
||||||
fun authHmacSha512Verify(mac: UByteArray, message: UByteArray, key: UByteArray) : Boolean
|
/**
|
||||||
|
* Verify that given message, secret key and tag, a newly calculated tag matches the received HMAC-SHA512 tag.
|
||||||
|
*/
|
||||||
|
fun authHmacSha512Verify(tag: UByteArray, message: UByteArray, key: UByteArray) : Boolean
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
# Package com.ionspin.kotlin.crypto.auth
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
Authentication is a process of generating authentication data (tag) for a certain message. Its purpose is to assure
|
||||||
|
that the data hasn't been corrupted or tampered with during the transport.
|
||||||
|
|
||||||
|
In general, it works like this:
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
- Message to authenticate
|
||||||
|
- Key to use for authentication
|
||||||
|
|
||||||
|
Sending side algorithm:
|
||||||
|
1. Apply MAC to message
|
||||||
|
1. Send the message + authentication data (tag)
|
||||||
|
|
||||||
|
Receiving side:
|
||||||
|
1. Apply the MAC to the received message
|
||||||
|
1. If the generated authenticated data (tag), and the received authentication data (received tag) match, proceed, otherwise sound the alarm and stop.
|
||||||
|
1. Return the message to the user
|
@ -19,6 +19,9 @@ data class BoxEncryptedDataAndTag(val ciphertext: UByteArray, val tag: UByteArra
|
|||||||
|
|
||||||
class BoxCorruptedOrTamperedDataException() : RuntimeException("MAC validation failed. Data is corrupted or tampered with.")
|
class BoxCorruptedOrTamperedDataException() : RuntimeException("MAC validation failed. Data is corrupted or tampered with.")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Box API uses public-key (asymmetric) encryption to
|
||||||
|
*/
|
||||||
expect object Box {
|
expect object Box {
|
||||||
/**
|
/**
|
||||||
* The crypto_box_keypair() function randomly generates a secret key and a corresponding public key.
|
* The crypto_box_keypair() function randomly generates a secret key and a corresponding public key.
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
# Package com.ionspin.kotlin.crypto.box
|
||||||
|
|
||||||
|
## Box API - Asymmetric/Public-key authenticated encryption
|
||||||
|
|
||||||
|
Public key encryption is a system that relies on a pair of keys to establish secure communication.
|
||||||
|
|
||||||
|
A simplified overview of communication between Bob and Alice using public-key encryption:
|
||||||
|
#### Key exchange
|
||||||
|
1. Alice creates 2 keys, one public, one private (public key is actually calculated from the private key)
|
||||||
|
1. Bob creates 2 keys, one public, one private
|
||||||
|
1. Alice sends her **public** key to Bob
|
||||||
|
1. Bob does the same and sends his **public** key to Alice
|
||||||
|
|
||||||
|
#### Encryption
|
||||||
|
|
||||||
|
Alice wants to establish a secure communication channel with Bob, they already exchanged public keys in previous steps.
|
||||||
|
|
||||||
|
1. Alice uses Bobs **private** key to encrypt a *secret value* (Usually just a key for symmetric encryption)
|
||||||
|
1. Alice sends encrypted data to Bob
|
||||||
|
1. Bob is the only one who has the matching private key, and can decrypt the data
|
||||||
|
1. Bob and Alice now posses the same *secret value* and can start communicating (i.e. by using XChaCha20Poly1305
|
||||||
|
symmetric encryption and using the *secret value* as the symmetric key)
|
||||||
|
|
||||||
|
Bob would do the same if he wanted to initiate the secure communication.
|
||||||
|
|
||||||
|
This set of functions also contains another use case called `sealed boxes` in libsodium.
|
||||||
|
Sealed box is designed to anonymously send a message to a recipient. Libsodium documentation explains it as follows:
|
||||||
|
> A message is encrypted using an ephemeral key pair, whose secret part is destroyed right after the encryption process.
|
||||||
|
Without knowing the secret key used for a given message, the sender cannot decrypt its own message later. And without additional data, a message cannot be correlated with the identity of its sender.
|
||||||
|
|
||||||
|
|
@ -21,14 +21,34 @@ data class GenericHashState(val hashLength: Int, val internalState: GenericHashS
|
|||||||
|
|
||||||
|
|
||||||
expect object GenericHash {
|
expect object GenericHash {
|
||||||
|
/**
|
||||||
|
* Request computing a hash of message, with a specific hash length and optional key. The specific hash length can be
|
||||||
|
* between [crypto_generichash_blake2b_BYTES_MIN] and [crypto_generichash_blake2b_BYTES_MAX]. If the key is provided
|
||||||
|
* it needs the hash will be different for each different key.
|
||||||
|
*/
|
||||||
|
fun genericHash(message : UByteArray, requestedHashLength: Int = crypto_generichash_BYTES, key : UByteArray? = null) : UByteArray
|
||||||
|
|
||||||
fun genericHash(message : UByteArray, requestedHashLength: Int, key : UByteArray? = null) : UByteArray
|
/**
|
||||||
|
* Prepare a Generic Hash State object that will be used to compute hash of data with arbitrary length. Secific hash length
|
||||||
|
* can be requested
|
||||||
|
*/
|
||||||
|
fun genericHashInit(requestedHashLength: Int = crypto_generichash_BYTES, key : UByteArray? = null) : GenericHashState
|
||||||
|
|
||||||
fun genericHashInit(requestedHashLength: Int, key : UByteArray? = null) : GenericHashState
|
/**
|
||||||
|
* Feed another chunk of message to the updateable hash object
|
||||||
|
*/
|
||||||
fun genericHashUpdate(state: GenericHashState, messagePart : UByteArray)
|
fun genericHashUpdate(state: GenericHashState, messagePart : UByteArray)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feed the last chunk of message to the updateable hash object. This returns the actual hash.
|
||||||
|
*/
|
||||||
fun genericHashFinal(state : GenericHashState) : UByteArray
|
fun genericHashFinal(state : GenericHashState) : UByteArray
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a key of length [crypto_generichash_blake2b_KEYBYTES] that can be used with the generic hash funciton
|
||||||
|
*/
|
||||||
fun genericHashKeygen() : UByteArray
|
fun genericHashKeygen() : UByteArray
|
||||||
|
|
||||||
// ---- Not present in LazySodium nor libsodium.js
|
// ---- Not present in LazySodium nor libsodium.js
|
||||||
// fun blake2b(message : UByteArray, requestedHashLength: Int, key : UByteArray? = null) : UByteArray
|
// fun blake2b(message : UByteArray, requestedHashLength: Int, key : UByteArray? = null) : UByteArray
|
||||||
//
|
//
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
# Package com.ionspin.kotlin.crypto.generichash
|
||||||
|
|
||||||
|
## Generic hash
|
||||||
|
|
||||||
|
Generic hash package provides a easy to use hashing API that computes fixed-length fingerprint for an arbitrary long message.
|
||||||
|
|
||||||
|
In this case hashing is a process of mapping a set of input bytes to a fixed length (32 bytes) output. Loosely speaking
|
||||||
|
hash function should be practically irreversible and resistant to collisions (a case where two different inputs result in a same output)
|
||||||
|
|
||||||
|
Some examples of hash function usage:
|
||||||
|
- Verifying data integrity, i.e. downloading a file and it's hash and then recalculating the hash of the downloaded
|
||||||
|
file to verify that it hasn't changed
|
||||||
|
- Creating unique identifiers to index long data
|
||||||
|
- Password verification, i.e. server stores just the hash of the users password and then when user wants to log in, they send
|
||||||
|
the password, which server then hashes and compares to the stored hash. This way in case of breach of server security cleartext
|
||||||
|
passwords are not revealed. With that said **DONT USE GENERIC HASH FOR PASSWORD HASHING**. Use PasswordHash funcitons.
|
||||||
|
|
||||||
|
Underneath this set of functions uses BLAKE2b secure hash function, Here is what Libsodium documentation says about it
|
||||||
|
>The crypto_generichash_* function set is implemented using BLAKE2b, a simple, standardized (RFC 7693) secure hash
|
||||||
|
>function that is as strong as SHA-3 but faster than SHA-1 and MD5.
|
||||||
|
>Unlike MD5, SHA-1 and SHA-256, this function is safe against hash length extension attacks.
|
||||||
|
>BLAKE2b is not suitable for hashing passwords. For this purpose, use the crypto_pwhash API documented
|
||||||
|
>in the Password Hashing section.
|
@ -13,6 +13,10 @@ fun String.encodeToUByteArray() : UByteArray{
|
|||||||
return encodeToByteArray().asUByteArray()
|
return encodeToByteArray().asUByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun UByteArray.decodeFromUByteArray() : String {
|
||||||
|
return asByteArray().decodeToString()
|
||||||
|
}
|
||||||
|
|
||||||
fun UByteArray.toHexString() : String {
|
fun UByteArray.toHexString() : String {
|
||||||
return this.joinToString(separator = "") {
|
return this.joinToString(separator = "") {
|
||||||
if (it <= 0x0FU) {
|
if (it <= 0x0FU) {
|
||||||
|
@ -26,7 +26,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actual fun xChaCha20Poly1305IetfDecrypt(
|
actual fun xChaCha20Poly1305IetfDecrypt(
|
||||||
ciphertext: UByteArray,
|
ciphertextAndTag: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
nonce: UByteArray,
|
nonce: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
@ -34,7 +34,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
try {
|
try {
|
||||||
return getSodium().crypto_aead_xchacha20poly1305_ietf_decrypt(
|
return getSodium().crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||||
null,
|
null,
|
||||||
ciphertext.toUInt8Array(),
|
ciphertextAndTag.toUInt8Array(),
|
||||||
associatedData.toUInt8Array(),
|
associatedData.toUInt8Array(),
|
||||||
nonce.toUInt8Array(),
|
nonce.toUInt8Array(),
|
||||||
key.toUInt8Array()
|
key.toUInt8Array()
|
||||||
@ -100,7 +100,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actual fun chaCha20Poly1305IetfDecrypt(
|
actual fun chaCha20Poly1305IetfDecrypt(
|
||||||
ciphertext: UByteArray,
|
ciphertextAndTag: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
nonce: UByteArray,
|
nonce: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
@ -108,7 +108,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
try {
|
try {
|
||||||
return getSodium().crypto_aead_chacha20poly1305_ietf_decrypt(
|
return getSodium().crypto_aead_chacha20poly1305_ietf_decrypt(
|
||||||
null,
|
null,
|
||||||
ciphertext.toUInt8Array(),
|
ciphertextAndTag.toUInt8Array(),
|
||||||
associatedData.toUInt8Array(),
|
associatedData.toUInt8Array(),
|
||||||
nonce.toUInt8Array(),
|
nonce.toUInt8Array(),
|
||||||
key.toUInt8Array()
|
key.toUInt8Array()
|
||||||
@ -174,7 +174,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actual fun chaCha20Poly1305Decrypt(
|
actual fun chaCha20Poly1305Decrypt(
|
||||||
ciphertext: UByteArray,
|
ciphertextAndTag: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
nonce: UByteArray,
|
nonce: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
@ -182,7 +182,7 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
try {
|
try {
|
||||||
return getSodium().crypto_aead_chacha20poly1305_decrypt(
|
return getSodium().crypto_aead_chacha20poly1305_decrypt(
|
||||||
null,
|
null,
|
||||||
ciphertext.toUInt8Array(),
|
ciphertextAndTag.toUInt8Array(),
|
||||||
associatedData.toUInt8Array(),
|
associatedData.toUInt8Array(),
|
||||||
nonce.toUInt8Array(),
|
nonce.toUInt8Array(),
|
||||||
key.toUInt8Array()
|
key.toUInt8Array()
|
||||||
|
@ -3,7 +3,6 @@ package com.ionspin.kotlin.crypto.auth
|
|||||||
import com.ionspin.kotlin.crypto.getSodium
|
import com.ionspin.kotlin.crypto.getSodium
|
||||||
import ext.libsodium.com.ionspin.kotlin.crypto.toUByteArray
|
import ext.libsodium.com.ionspin.kotlin.crypto.toUByteArray
|
||||||
import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array
|
import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array
|
||||||
import org.khronos.webgl.Uint8Array
|
|
||||||
|
|
||||||
actual object Auth {
|
actual object Auth {
|
||||||
actual fun authKeygen(): UByteArray {
|
actual fun authKeygen(): UByteArray {
|
||||||
@ -18,9 +17,9 @@ actual object Auth {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun authVerify(mac: UByteArray, message: UByteArray, key: UByteArray): Boolean {
|
actual fun authVerify(tag: UByteArray, message: UByteArray, key: UByteArray): Boolean {
|
||||||
return getSodium().crypto_auth_verify(
|
return getSodium().crypto_auth_verify(
|
||||||
mac.toUInt8Array(),
|
tag.toUInt8Array(),
|
||||||
message.toUInt8Array(),
|
message.toUInt8Array(),
|
||||||
key.toUInt8Array()
|
key.toUInt8Array()
|
||||||
)
|
)
|
||||||
@ -38,12 +37,12 @@ actual object Auth {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actual fun authHmacSha256Verify(
|
actual fun authHmacSha256Verify(
|
||||||
mac: UByteArray,
|
tag: UByteArray,
|
||||||
message: UByteArray,
|
message: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return getSodium().crypto_auth_hmacsha256_verify(
|
return getSodium().crypto_auth_hmacsha256_verify(
|
||||||
mac.toUInt8Array(),
|
tag.toUInt8Array(),
|
||||||
message.toUInt8Array(),
|
message.toUInt8Array(),
|
||||||
key.toUInt8Array()
|
key.toUInt8Array()
|
||||||
)
|
)
|
||||||
@ -61,12 +60,12 @@ actual object Auth {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actual fun authHmacSha512Verify(
|
actual fun authHmacSha512Verify(
|
||||||
mac: UByteArray,
|
tag: UByteArray,
|
||||||
message: UByteArray,
|
message: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return getSodium().crypto_auth_hmacsha512_verify(
|
return getSodium().crypto_auth_hmacsha512_verify(
|
||||||
mac.toUInt8Array(),
|
tag.toUInt8Array(),
|
||||||
message.toUInt8Array(),
|
message.toUInt8Array(),
|
||||||
key.toUInt8Array()
|
key.toUInt8Array()
|
||||||
)
|
)
|
||||||
|
@ -29,18 +29,18 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actual fun xChaCha20Poly1305IetfDecrypt(
|
actual fun xChaCha20Poly1305IetfDecrypt(
|
||||||
ciphertext: UByteArray,
|
ciphertextAndTag: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
nonce: UByteArray,
|
nonce: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = UByteArray(ciphertext.size - crypto_aead_xchacha20poly1305_ietf_ABYTES)
|
val message = UByteArray(ciphertextAndTag.size - crypto_aead_xchacha20poly1305_ietf_ABYTES)
|
||||||
val validationResult = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(
|
val validationResult = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
ciphertext.asByteArray(),
|
ciphertextAndTag.asByteArray(),
|
||||||
ciphertext.size.toLong(),
|
ciphertextAndTag.size.toLong(),
|
||||||
associatedData.asByteArray(),
|
associatedData.asByteArray(),
|
||||||
associatedData.size.toLong(),
|
associatedData.size.toLong(),
|
||||||
nonce.asByteArray(),
|
nonce.asByteArray(),
|
||||||
@ -122,18 +122,18 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actual fun chaCha20Poly1305IetfDecrypt(
|
actual fun chaCha20Poly1305IetfDecrypt(
|
||||||
ciphertext: UByteArray,
|
ciphertextAndTag: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
nonce: UByteArray,
|
nonce: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = UByteArray(ciphertext.size - crypto_aead_chacha20poly1305_ietf_ABYTES)
|
val message = UByteArray(ciphertextAndTag.size - crypto_aead_chacha20poly1305_ietf_ABYTES)
|
||||||
val validationResult = sodium.crypto_aead_chacha20poly1305_ietf_decrypt(
|
val validationResult = sodium.crypto_aead_chacha20poly1305_ietf_decrypt(
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
ciphertext.asByteArray(),
|
ciphertextAndTag.asByteArray(),
|
||||||
ciphertext.size.toLong(),
|
ciphertextAndTag.size.toLong(),
|
||||||
associatedData.asByteArray(),
|
associatedData.asByteArray(),
|
||||||
associatedData.size.toLong(),
|
associatedData.size.toLong(),
|
||||||
nonce.asByteArray(),
|
nonce.asByteArray(),
|
||||||
@ -215,18 +215,18 @@ actual object AuthenticatedEncryptionWithAssociatedData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actual fun chaCha20Poly1305Decrypt(
|
actual fun chaCha20Poly1305Decrypt(
|
||||||
ciphertext: UByteArray,
|
ciphertextAndTag: UByteArray,
|
||||||
associatedData: UByteArray,
|
associatedData: UByteArray,
|
||||||
nonce: UByteArray,
|
nonce: UByteArray,
|
||||||
key: UByteArray
|
key: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = UByteArray(ciphertext.size - crypto_aead_chacha20poly1305_ABYTES)
|
val message = UByteArray(ciphertextAndTag.size - crypto_aead_chacha20poly1305_ABYTES)
|
||||||
val validationResult = sodium.crypto_aead_chacha20poly1305_decrypt(
|
val validationResult = sodium.crypto_aead_chacha20poly1305_decrypt(
|
||||||
message.asByteArray(),
|
message.asByteArray(),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
ciphertext.asByteArray(),
|
ciphertextAndTag.asByteArray(),
|
||||||
ciphertext.size.toLong(),
|
ciphertextAndTag.size.toLong(),
|
||||||
associatedData.asByteArray(),
|
associatedData.asByteArray(),
|
||||||
associatedData.size.toLong(),
|
associatedData.size.toLong(),
|
||||||
nonce.asByteArray(),
|
nonce.asByteArray(),
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user