Merge pull request #13 from ionspin/extract-interfaces
Extract interfaces
This commit is contained in:
		
						commit
						c5cb66d087
					
				
							
								
								
									
										16
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -13,3 +13,19 @@ build/
 | 
				
			|||||||
/package.json
 | 
					/package.json
 | 
				
			||||||
/multiplatform-crypto/src/jsMain/npm/node_modules
 | 
					/multiplatform-crypto/src/jsMain/npm/node_modules
 | 
				
			||||||
/multiplatform-crypto/src/jsMain/npm/package-lock.json
 | 
					/multiplatform-crypto/src/jsMain/npm/package-lock.json
 | 
				
			||||||
 | 
					/multiplatform-crypto-delegated/node_modules
 | 
				
			||||||
 | 
					/multiplatform-crypto-delegated/package.json
 | 
				
			||||||
 | 
					/multiplatform-crypto-delegated/package-lock.json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/sodiumWrapper/include/
 | 
				
			||||||
 | 
					/sodiumWrapper/lib/
 | 
				
			||||||
 | 
					/sodiumWrapper/ios-include/
 | 
				
			||||||
 | 
					/sodiumWrapper/ios-lib/
 | 
				
			||||||
 | 
					/sodiumWrapper/static-arm64/
 | 
				
			||||||
 | 
					/sodiumWrapper/static-arm32/
 | 
				
			||||||
 | 
					/sodiumWrapper/static-ios/
 | 
				
			||||||
 | 
					/sodiumWrapper/static-linux-x86-64/
 | 
				
			||||||
 | 
					/sodiumWrapper/static-macos-x86-64/
 | 
				
			||||||
 | 
					/sodiumWrapper/static-mingw-x86-64/
 | 
				
			||||||
 | 
					/sodiumWrapper/static-tvos/
 | 
				
			||||||
 | 
					/sodiumWrapper/static-watchos/
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					[submodule "sodiumWrapper/libsodium"]
 | 
				
			||||||
 | 
						path = sodiumWrapper/libsodium
 | 
				
			||||||
 | 
						url = https://github.com/ionspin/libsodium.git
 | 
				
			||||||
							
								
								
									
										118
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								.travis.yml
									
									
									
									
									
								
							@ -1,33 +1,74 @@
 | 
				
			|||||||
matrix:
 | 
					matrix:
 | 
				
			||||||
  include:
 | 
					  include:
 | 
				
			||||||
    - os: linux
 | 
					    - os: linux
 | 
				
			||||||
 | 
					      name: linux
 | 
				
			||||||
      language: java
 | 
					      language: java
 | 
				
			||||||
      jdk: openjdk12
 | 
					      jdk: openjdk12
 | 
				
			||||||
#      before_script:
 | 
					
 | 
				
			||||||
#        - wget https://github.com/sormuras/bach/raw/master/install-jdk.sh
 | 
					 | 
				
			||||||
#        - source install-jdk.sh --url 'https://api.adoptopenjdk.net/v2/binary/releases/openjdk12?openjdk_impl=hotspot&os=linux&arch=x64&release=latest&heap_size=normal&type=jdk'
 | 
					 | 
				
			||||||
#        - java --version
 | 
					 | 
				
			||||||
      env:
 | 
					      env:
 | 
				
			||||||
        KBUILD=linux
 | 
					        KBUILD=linux
 | 
				
			||||||
        JAVA_OPTS=-Xmx2g
 | 
					        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:
 | 
					      script:
 | 
				
			||||||
        - 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./linuxBuild.sh; fi'
 | 
					        - 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./linuxBuild.sh; fi'
 | 
				
			||||||
        - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./linuxBuildAndPublish.sh; fi'
 | 
					        - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./linuxBuildAndPublish.sh; fi'
 | 
				
			||||||
 | 
					#       OSX macos/ios
 | 
				
			||||||
    - os: osx
 | 
					    - os: osx
 | 
				
			||||||
 | 
					      name: osx-mac-ios
 | 
				
			||||||
      osx_image: xcode11.4
 | 
					      osx_image: xcode11.4
 | 
				
			||||||
      language: java
 | 
					      language: java
 | 
				
			||||||
      jdk: openjdk12
 | 
					      jdk: openjdk12
 | 
				
			||||||
#      before_script:
 | 
					      install: true
 | 
				
			||||||
#        - wget https://github.com/sormuras/bach/raw/master/install-jdk.sh
 | 
					 | 
				
			||||||
#        - source install-jdk.sh --url 'https://api.adoptopenjdk.net/v2/binary/releases/openjdk12?openjdk_impl=hotspot&os=linux&arch=x64&release=latest&heap_size=normal&type=jdk'
 | 
					 | 
				
			||||||
#        - java --version
 | 
					 | 
				
			||||||
      env:
 | 
					      env:
 | 
				
			||||||
        KBUILD=linux
 | 
					        KBUILD=linux
 | 
				
			||||||
        JAVA_OPTS=-Xmx2g
 | 
					        JAVA_OPTS=-Xmx2g
 | 
				
			||||||
      script:
 | 
					      script:
 | 
				
			||||||
        - 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./macBuild.sh; fi'
 | 
					        - 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./macBuild-mac-ios.sh; fi'
 | 
				
			||||||
        - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./macBuildAndPublish.sh; fi'
 | 
					        - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./macBuildAndPublish-mac-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 pure
 | 
				
			||||||
 | 
					    - os: osx
 | 
				
			||||||
 | 
					      name: osx-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.sh; fi'
 | 
				
			||||||
 | 
					        - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./macBuildAndPublish-pure.sh; fi'
 | 
				
			||||||
    - os: windows
 | 
					    - os: windows
 | 
				
			||||||
 | 
					      name: windwos-pure
 | 
				
			||||||
      language: shell
 | 
					      language: shell
 | 
				
			||||||
      jdk: openjdk12
 | 
					      jdk: openjdk12
 | 
				
			||||||
      env:
 | 
					      env:
 | 
				
			||||||
@ -37,15 +78,68 @@ matrix:
 | 
				
			|||||||
      before_install:
 | 
					      before_install:
 | 
				
			||||||
        - curl "${GRAVIS}.install-jdk-travis.sh" --output ~/.install-jdk-travis.sh
 | 
					        - curl "${GRAVIS}.install-jdk-travis.sh" --output ~/.install-jdk-travis.sh
 | 
				
			||||||
        - source ~/.install-jdk-travis.sh
 | 
					        - source ~/.install-jdk-travis.sh
 | 
				
			||||||
 | 
					      install: true
 | 
				
			||||||
      script:
 | 
					      script:
 | 
				
			||||||
        - 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then ./gradlew build ; fi'
 | 
					        - 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then $shell ./windowsBuild-pure.sh; fi'
 | 
				
			||||||
        - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then ./gradlew build publishMingwx64PublicationToSnapshotRepository; 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 ./windowsBuildAndPublish-delegated.sh; fi'
 | 
				
			||||||
cache:
 | 
					cache:
 | 
				
			||||||
  directories:
 | 
					  directories:
 | 
				
			||||||
    - $HOME/.m2/
 | 
					    - $HOME/.m2/
 | 
				
			||||||
    - $HOME/.gradle/caches/
 | 
					    - $HOME/.gradle/caches/
 | 
				
			||||||
    - $HOME/.gradle/wrapper/
 | 
					    - $HOME/.gradle/wrapper/
 | 
				
			||||||
    - $HOME/.konan/cache
 | 
					    - $HOME/.konan/cache
 | 
				
			||||||
 | 
					    - $HOME/.konan/dependencies
 | 
				
			||||||
 | 
					    - $HOME/AppData/Local/Temp/chocolatey
 | 
				
			||||||
 | 
					    - /C/tools/msys64
 | 
				
			||||||
branches:
 | 
					branches:
 | 
				
			||||||
  only:
 | 
					  only:
 | 
				
			||||||
    - master
 | 
					    - master
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										43
									
								
								EXTERNAL_LICENSES
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								EXTERNAL_LICENSES
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					Libraries used by multipatform-crypto-delegated follow:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Libsodium, licensed under ISC License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					* ISC License
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* Copyright (c) 2013-2020
 | 
				
			||||||
 | 
					* Frank Denis <j at pureftpd dot org>
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* Permission to use, copy, modify, and/or distribute this software for any
 | 
				
			||||||
 | 
					* purpose with or without fee is hereby granted, provided that the above
 | 
				
			||||||
 | 
					* copyright notice and this permission notice appear in all copies.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
				
			||||||
 | 
					* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
				
			||||||
 | 
					* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
				
			||||||
 | 
					* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
				
			||||||
 | 
					* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
				
			||||||
 | 
					* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Libsodium.js (temporarily included libsodium-wrappers-sumo-0.7.6.tgz packed npm package with additional sha256 and sha512 multipart wrappers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2015-2020
 | 
				
			||||||
 | 
					Ahmad Ben Mrad <batikhsouri at gmail dot org>
 | 
				
			||||||
 | 
					Frank Denis <j at pureftpd dot org>
 | 
				
			||||||
 | 
					Ryan Lester <ryan at cyph dot com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission to use, copy, modify, and/or distribute this software for any
 | 
				
			||||||
 | 
					purpose with or without fee is hereby granted, provided that the above
 | 
				
			||||||
 | 
					copyright notice and this permission notice appear in all copies.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
				
			||||||
 | 
					WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
				
			||||||
 | 
					ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
				
			||||||
 | 
					WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
				
			||||||
 | 
					ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
				
			||||||
 | 
					OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										115
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										115
									
								
								README.md
									
									
									
									
									
								
							@ -5,58 +5,97 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Kotlin Multiplatform Crypto is a library for various cryptographic applications. 
 | 
					Kotlin Multiplatform Crypto is a library for various cryptographic applications. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This is an extremely early release, currently only consisting of Blake2b and SHA256 and 512.
 | 
					The library comes in two flavors `multiplatform-crypto` and `multiplatform-crypto-delegated`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `multiplatform-crypto` contains pure kotlin implementations, is not reviewed, should be considered unsafe and only 
 | 
				
			||||||
 | 
					for prototyping or experimentation purposes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `multiplatform-crypto-delegated` relies on platform specific implementations, like libsodium, but care should still be taken that the kotlin code is not reviewed or proven safe.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					APIs of both variants are identical. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Supported platforms by variant
 | 
				
			||||||
 | 
					|Platform|Pure variant| Delegated variant|
 | 
				
			||||||
 | 
					|--------|------------|------------------|
 | 
				
			||||||
 | 
					|Linux X86 64|          :heavy_check_mark: | :heavy_check_mark: |
 | 
				
			||||||
 | 
					|Linux Arm 64|          :heavy_check_mark: | :heavy_check_mark: |
 | 
				
			||||||
 | 
					|Linux Arm 32|          :heavy_check_mark: | :x: |
 | 
				
			||||||
 | 
					|macOS X86 64|          :heavy_check_mark: | :heavy_check_mark: |
 | 
				
			||||||
 | 
					|iOS x86 64 |           :heavy_check_mark: | :heavy_check_mark: |
 | 
				
			||||||
 | 
					|iOS Arm 64 |           :heavy_check_mark: | :heavy_check_mark: |
 | 
				
			||||||
 | 
					|iOS Arm 32 |           :heavy_check_mark: | :heavy_check_mark: |
 | 
				
			||||||
 | 
					|watchOS X86 32 |       :heavy_check_mark: | :heavy_check_mark: |
 | 
				
			||||||
 | 
					|watchOS Arm 64(_32) |  :heavy_check_mark: | :heavy_check_mark: |
 | 
				
			||||||
 | 
					|watchos Arm 32 |       :heavy_check_mark: | :heavy_check_mark: |
 | 
				
			||||||
 | 
					|tvOS X86 64 |          :heavy_check_mark: | :heavy_check_mark: |
 | 
				
			||||||
 | 
					|tvOS Arm 64 |          :heavy_check_mark: | :heavy_check_mark: |
 | 
				
			||||||
 | 
					|minGW X86 64|          :heavy_check_mark: | :heavy_check_mark: |
 | 
				
			||||||
 | 
					|minGW X86 32|          :x:                | :x: | 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
API is very opinionated, ment to be used on both encrypting and decrypting side. The idea is that API leaves less room for 
 | 
					 | 
				
			||||||
errors when using it.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Notes & Roadmap
 | 
					## Notes & Roadmap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**The API will move fast and break often until v1.0**
 | 
					**The API will move fast and break often until v1.0**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Make SHA hashes "updatable" like Blake2b
 | 
					Next steps:
 | 
				
			||||||
 | 
					- Expand API (AEAD, ECC ...)
 | 
				
			||||||
After that tenative plan is to add 25519 curve based signing and key exchange next.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Should I use this in production?
 | 
					## Should I use this in production?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
No.
 | 
					No, until it is reviewed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Should I use this in code that is critical in any way, shape or form?
 | 
					## Should I use this in code that is *critical* in any way, shape or form?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
No.
 | 
					No, but even if after being warned you decide to, then use `multiplatform-crypto-delegated` as it relies on reputable libraries.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Why?
 | 
					## Why?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This is an experimental implementation, mostly for expanding personal understanding of cryptography. 
 | 
					This is an experimental implementation, mostly for expanding personal understanding of cryptography. 
 | 
				
			||||||
It's not peer reviewed, not guaranteed to be bug free, and not guaranteed to be secure.
 | 
					It's not peer reviewed, not guaranteed to be bug free, and not guaranteed to be secure.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Integration
 | 
					## Currently supported 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Hashing functions
 | 
				
			||||||
 | 
					 | 
				
			||||||
## Hashing functions
 | 
					 | 
				
			||||||
* Blake2b
 | 
					* Blake2b
 | 
				
			||||||
* SHA512
 | 
					* SHA512
 | 
				
			||||||
* SHA256
 | 
					* SHA256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Symmetric cipher
 | 
					### Symmetric cipher
 | 
				
			||||||
* AES
 | 
					* AES
 | 
				
			||||||
  * Modes: CBC, CTR
 | 
					  * Modes: CBC, CTR
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
## Key Derivation 
 | 
					### Key Derivation 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* Argon2
 | 
					* Argon2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## AEAD
 | 
					### AEAD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TODO()
 | 
					TODO()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Delegated flavor dependancy table
 | 
				
			||||||
 | 
					The following table describes which library is used for particular cryptographic primitive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| Primitive | JVM | JS | Native |
 | 
				
			||||||
 | 
					| ----------|-----|----|--------|
 | 
				
			||||||
 | 
					| Blake2b | LazySodium | libsodium.js | libsodium |
 | 
				
			||||||
 | 
					| SHA256 | LazySodium | libsodium.js | libsodium |
 | 
				
			||||||
 | 
					| SHA512 | LazySodium | libsodium.js | libsodium |
 | 
				
			||||||
 | 
					| AES-CBC | LazySodium | libsodium.js | libsodium |
 | 
				
			||||||
 | 
					| AES-CTR | LazySodium | libsodium.js | libsodium |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Integration
 | 
					## Integration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Gradle
 | 
					#### Gradle
 | 
				
			||||||
 | 
					Kotlin 
 | 
				
			||||||
```kotlin
 | 
					```kotlin
 | 
				
			||||||
implementation("com.ionspin.kotlin:multiplatform-crypto:0.0.2")
 | 
					implementation("com.ionspin.kotlin:multiplatform-crypto:0.0.5")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					implementation("com.ionspin.kotlin:multiplatform-crypto-delegated:0.0.5")
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Snapshot builds
 | 
					#### Snapshot builds
 | 
				
			||||||
@ -66,12 +105,19 @@ repositories {
 | 
				
			|||||||
        url = uri("https://oss.sonatype.org/content/repositories/snapshots")
 | 
					        url = uri("https://oss.sonatype.org/content/repositories/snapshots")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
implementation("com.ionspin.kotlin:multiplatform-crypto:0.0.3-SNAPSHOT")
 | 
					implementation("com.ionspin.kotlin:multiplatform-crypto:0.0.6-SNAPSHOT")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Usage
 | 
					## Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Helper functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All API take `UByteArray` as message/key/nonce/etc parameter. For convenience when working with strings we provide
 | 
				
			||||||
 | 
					`String.enocdeToUbyteArray()` extensions function, and `UByteArray.toHexString` extension function. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					More convenience functions will be added.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Hashes
 | 
					### Hashes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Hashes are provided in two versions, "stateless", usually the companion object of the hash, 
 | 
					Hashes are provided in two versions, "stateless", usually the companion object of the hash, 
 | 
				
			||||||
@ -87,23 +133,23 @@ You need to deliver the complete data that is to be hashed in one go
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```kotlin
 | 
					```kotlin
 | 
				
			||||||
val input = "abc"
 | 
					val input = "abc"
 | 
				
			||||||
val result = Blake2b.digest(input)
 | 
					val result = Crypto.Blake2b.stateless(input.encodeToUByteArray())
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Result is returned as a `Array<Byte>`
 | 
					Result is returned as a `UByteArray`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### Updatable instance version
 | 
					##### Updatable instance version
 | 
				
			||||||
You can create an instance and feed the data by using `update(input : Array<Byte>)` call. Once all data is supplied,
 | 
					You can create an instance and feed the data by using `update(input : UByteArray)` call. Once all data is supplied,
 | 
				
			||||||
you should call `digest()` or `digestString()` convenience method that converts the `Array<Byte>` into hexadecimal string.
 | 
					you should call `digest()`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you want to use Blake2b with a key, you should supply it when creating the `Blake2b` instance.
 | 
					If you want to use Blake2b with a key, you should supply it when creating the `Blake2b` instance.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```kotlin
 | 
					```kotlin
 | 
				
			||||||
val test = "abc"
 | 
					val test = "abc"
 | 
				
			||||||
val key = "key"
 | 
					val key = "key"
 | 
				
			||||||
val blake2b = Blake2b(key)
 | 
					val blake2b = Crypto.Blake2b.updateable(key.encodeToUByteArray())
 | 
				
			||||||
blake2b.update(test)
 | 
					blake2b.update(test.encodeToUByteArray())
 | 
				
			||||||
val result = blake2b.digest()
 | 
					val result = blake2b.digest().toHexString()
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
After digest is called, the instance is reset and can be reused (Keep in mind key stays the same for the particular instance).
 | 
					After digest is called, the instance is reset and can be reused (Keep in mind key stays the same for the particular instance).
 | 
				
			||||||
@ -111,36 +157,37 @@ After digest is called, the instance is reset and can be reused (Keep in mind ke
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
##### Stateless version
 | 
					##### Stateless version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You need to deliver the complete data that is to be hashed in one go. You can either provide the `Array<Byte>` as input
 | 
					You need to deliver the complete data that is to be hashed in one go. You can either provide the `UByteArray` as input
 | 
				
			||||||
or `String`. Result is always returned as `Array<Byte>` (At least in verision 0.0.1)
 | 
					or `String`. Result is always returned as `UByteArray` (At least in verision 0.0.1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```kotlin
 | 
					```kotlin
 | 
				
			||||||
val input = "abc"
 | 
					val input = "abc"
 | 
				
			||||||
val result = Sha256.digest(input)
 | 
					val result = Crypto.Sha256.stateless(input.encodeToUByteArray())
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```kotlin
 | 
					```kotlin
 | 
				
			||||||
val input ="abc"
 | 
					val input ="abc"
 | 
				
			||||||
val result = Sha512.digest(message = input.encodeToByteArray().map { it.toUByte() }.toTypedArray())
 | 
					val result = Crypto.Sha512.stateless(input.encodeToUByteArray())
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Result is returned as a `Array<Byte>`
 | 
					Result is returned as a `UByteArray`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### Updateable version
 | 
					##### Updateable version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Or you can use the updatable instance version
 | 
					Or you can use the updatable instance version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```kotlin
 | 
					```kotlin
 | 
				
			||||||
val sha256 = Sha256()
 | 
					val sha256 = Crypto.Sha256.updateable()
 | 
				
			||||||
sha256.update("abc")
 | 
					sha256.update("abc".encodeToUByteArray())
 | 
				
			||||||
val result = sha256.digest()
 | 
					val result = sha256.digest()
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```kotlin
 | 
					```kotlin
 | 
				
			||||||
val sha512 = Sha512()
 | 
					val sha512 = Crypto.Sha512.updateable()
 | 
				
			||||||
sha512.update("abc")
 | 
					sha512.update("abc".encodeToUByteArray())
 | 
				
			||||||
val result = sha512.digest()
 | 
					val result = sha512.digest()
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Symmetric encryption 
 | 
					### Symmetric encryption 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### AES 
 | 
					#### AES 
 | 
				
			||||||
 | 
				
			|||||||
@ -40,6 +40,7 @@ allprojects {
 | 
				
			|||||||
        google()
 | 
					        google()
 | 
				
			||||||
        maven ("https://kotlin.bintray.com/kotlinx")
 | 
					        maven ("https://kotlin.bintray.com/kotlinx")
 | 
				
			||||||
        maven ("https://dl.bintray.com/kotlin/kotlin-eap")
 | 
					        maven ("https://dl.bintray.com/kotlin/kotlin-eap")
 | 
				
			||||||
 | 
					        maven ("https://kotlin.bintray.com/kotlin-dev")
 | 
				
			||||||
        jcenter()
 | 
					        jcenter()
 | 
				
			||||||
        maven {
 | 
					        maven {
 | 
				
			||||||
            url = uri("https://oss.sonatype.org/content/repositories/snapshots")
 | 
					            url = uri("https://oss.sonatype.org/content/repositories/snapshots")
 | 
				
			||||||
 | 
				
			|||||||
@ -21,5 +21,14 @@ plugins {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
repositories {
 | 
					repositories {
 | 
				
			||||||
 | 
					    mavenCentral()
 | 
				
			||||||
 | 
					    maven ("https://dl.bintray.com/kotlin/kotlin-eap")
 | 
				
			||||||
    jcenter()
 | 
					    jcenter()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dependencies {
 | 
				
			||||||
 | 
					    implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4-M2")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					System.setProperty("PROJECT_PATH", project.projectDir.parentFile.toString())
 | 
				
			||||||
 | 
					println("Path ${project.projectDir.parentFile}")
 | 
				
			||||||
 | 
				
			|||||||
@ -15,38 +15,57 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
object Versions {
 | 
					object Versions {
 | 
				
			||||||
    val kotlinCoroutines = "1.3.5-native-mt-1.4-M1"
 | 
					    val kotlinCoroutines = "1.3.5-native-mt-arm-1.4-M2-SNAPSHOT" //NOTE: my linux arm32 and arm64 build
 | 
				
			||||||
    val kotlin = "1.4-M1"
 | 
					    val kotlin = "1.4-M2"
 | 
				
			||||||
    val kotlinSerialization = "0.20.0-1.4-M1"
 | 
					    val kotlinSerialization = "0.20.0-1.4-M2"
 | 
				
			||||||
    val atomicfu = "0.14.2-1.4-M1"
 | 
					    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 = "0.9.18"
 | 
					    val dokkaPlugin = "0.9.18"
 | 
				
			||||||
 | 
					    val taskTreePlugin = "1.5"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val kotlinBigNumVersion = "0.1.6-SNAPSHOT"
 | 
					    val kotlinBigNumVersion = "0.1.6-1.4-M2-SNAPSHOT"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val lazySodium = "4.2.6"
 | 
				
			||||||
 | 
					    val jna = "5.5.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					object ReleaseInfo {
 | 
				
			||||||
 | 
					    val group = "com.ionspin.kotlin"
 | 
				
			||||||
 | 
					    val version = "0.1.0-SNAPSHOT"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
object Deps {
 | 
					object Deps {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    object Common {
 | 
					    object Common {
 | 
				
			||||||
        val stdLib = "stdlib-common"
 | 
					        val stdLib = "stdlib-common"
 | 
				
			||||||
        val test = "test-common"
 | 
					        val test = "test-common"
 | 
				
			||||||
        val testAnnotation = "test-annotations-common"
 | 
					        val testAnnotation = "test-annotations-common"
 | 
				
			||||||
        val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:${Versions.kotlinCoroutines}"
 | 
					//        val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:${Versions.kotlinCoroutines}"
 | 
				
			||||||
 | 
					        val coroutines = "com.ionspin.kotlin.coroutines:kotlinx-coroutines-core:${Versions.kotlinCoroutines}"
 | 
				
			||||||
        val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:${Versions.kotlinSerialization}"
 | 
					        val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:${Versions.kotlinSerialization}"
 | 
				
			||||||
        val atomicfu = "org.jetbrains.kotlinx:atomicfu:${Versions.atomicfu}"
 | 
					        val atomicfu = "com.ionspin.kotlin.atomicfu:atomicfu:${Versions.atomicfu}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val kotlinBigNum = "com.ionspin.kotlin:bignum:${Versions.kotlinBigNumVersion}"
 | 
					        val kotlinBigNum = "com.ionspin.kotlin:bignum:${Versions.kotlinBigNumVersion}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val apiProject = ":multiplatform-crypto-api"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    object Js {
 | 
					    object Js {
 | 
				
			||||||
        val stdLib = "stdlib-js"
 | 
					        val stdLib = "stdlib-js"
 | 
				
			||||||
        val test = "test-js"
 | 
					        val test = "test-js"
 | 
				
			||||||
        val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:${Versions.kotlinCoroutines}"
 | 
					//        val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:${Versions.kotlinCoroutines}"
 | 
				
			||||||
 | 
					        val coroutines = "com.ionspin.kotlin.coroutines:kotlinx-coroutines-core:${Versions.kotlinCoroutines}"
 | 
				
			||||||
        val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:${Versions.kotlinSerialization}"
 | 
					        val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:${Versions.kotlinSerialization}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        object Npm {
 | 
				
			||||||
 | 
					            val libsodium = Pair("libsodium-wrappers-sumo", "0.7.6")
 | 
				
			||||||
 | 
					//            val libsodiumWrappers = Pair("libsodium-wrappers-sumo", "0.7.6")
 | 
				
			||||||
 | 
					            val libsodiumWrappers = Pair("libsodium-wrappers-sumo", "file:${getProjectPath()}/multiplatform-crypto-delegated/libsodium-wrappers-sumo-0.7.6.tgz")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    object Jvm {
 | 
					    object Jvm {
 | 
				
			||||||
@ -54,20 +73,29 @@ object Deps {
 | 
				
			|||||||
        val test = "test"
 | 
					        val test = "test"
 | 
				
			||||||
        val testJUnit = "test-junit"
 | 
					        val testJUnit = "test-junit"
 | 
				
			||||||
        val reflection = "reflect"
 | 
					        val reflection = "reflect"
 | 
				
			||||||
        val coroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.kotlinCoroutines}"
 | 
					//        val coroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.kotlinCoroutines}"
 | 
				
			||||||
 | 
					        val coroutinesCore = "com.ionspin.kotlin.coroutines:kotlinx-coroutines-core:${Versions.kotlinCoroutines}"
 | 
				
			||||||
        val coroutinesjdk8 = "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:${Versions.kotlinCoroutines}"
 | 
					        val coroutinesjdk8 = "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:${Versions.kotlinCoroutines}"
 | 
				
			||||||
        val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime:${Versions.kotlinSerialization}"
 | 
					        val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime:${Versions.kotlinSerialization}"
 | 
				
			||||||
        val coroutinesTest = "org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.kotlinCoroutines}"
 | 
					//        val coroutinesTest = "org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.kotlinCoroutines}"
 | 
				
			||||||
 | 
					        val coroutinesTest = "com.ionspin.kotlin.coroutines:kotlinx-coroutines-test:${Versions.kotlinCoroutines}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        object Delegated {
 | 
				
			||||||
 | 
					            val lazysodium = "com.goterl.lazycode:lazysodium-java:${Versions.lazySodium}"
 | 
				
			||||||
 | 
					            val jna = "net.java.dev.jna:jna:${Versions.jna}"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    object iOs {
 | 
					    object iOs {
 | 
				
			||||||
        val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:${Versions.kotlinSerialization}"
 | 
					        val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:${Versions.kotlinSerialization}"
 | 
				
			||||||
        val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:${Versions.kotlinCoroutines}"
 | 
					//        val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:${Versions.kotlinCoroutines}"
 | 
				
			||||||
 | 
					        val coroutines = "com.ionspin.kotlin.coroutines:kotlinx-coroutines-core:${Versions.kotlinCoroutines}"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    object Native {
 | 
					    object Native {
 | 
				
			||||||
        val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:${Versions.kotlinSerialization}"
 | 
					        val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:${Versions.kotlinSerialization}"
 | 
				
			||||||
        val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:${Versions.kotlinCoroutines}"
 | 
					//        val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:${Versions.kotlinCoroutines}"
 | 
				
			||||||
 | 
					        val coroutines = "com.ionspin.kotlin.coroutines:kotlinx-coroutines-core:${Versions.kotlinCoroutines}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -81,5 +109,6 @@ object PluginsDeps {
 | 
				
			|||||||
    val mavenPublish = "maven-publish"
 | 
					    val mavenPublish = "maven-publish"
 | 
				
			||||||
    val signing = "signing"
 | 
					    val signing = "signing"
 | 
				
			||||||
    val dokka = "org.jetbrains.dokka"
 | 
					    val dokka = "org.jetbrains.dokka"
 | 
				
			||||||
 | 
					    val taskTree = "com.dorongold.task-tree"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										112
									
								
								buildSrc/src/main/kotlin/Utils.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								buildSrc/src/main/kotlin/Utils.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					import org.gradle.api.NamedDomainObjectContainer
 | 
				
			||||||
 | 
					import org.gradle.nativeplatform.platform.internal.Architectures
 | 
				
			||||||
 | 
					import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
 | 
				
			||||||
 | 
					import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
 | 
				
			||||||
 | 
					import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
 | 
				
			||||||
 | 
					import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
 | 
				
			||||||
 | 
					import java.io.File
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 30-May-2020
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					fun isInIdea() = System.getProperty("idea.active") == "true"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun isInTravis() = System.getenv("TRAVIS") == "true"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun getProjectPath() : String {
 | 
				
			||||||
 | 
					    val path = System.getProperty("PROJECT_PATH")
 | 
				
			||||||
 | 
					    return path
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun getHostOsName(): String {
 | 
				
			||||||
 | 
					    val target = System.getProperty("os.name")
 | 
				
			||||||
 | 
					    if (target == "Linux") return "linux"
 | 
				
			||||||
 | 
					    if (target.startsWith("Windows")) return "windows"
 | 
				
			||||||
 | 
					    if (target.startsWith("Mac")) return "macos"
 | 
				
			||||||
 | 
					    return "unknown"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun getHostArchitecture(): String {
 | 
				
			||||||
 | 
					    val architecture = System.getProperty("os.arch")
 | 
				
			||||||
 | 
					    DefaultNativePlatform.getCurrentArchitecture()
 | 
				
			||||||
 | 
					    println("Arch: $architecture")
 | 
				
			||||||
 | 
					    val resolvedArch = Architectures.forInput(architecture).name
 | 
				
			||||||
 | 
					    println("Resolved arch: $resolvedArch")
 | 
				
			||||||
 | 
					    return resolvedArch
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun KotlinMultiplatformExtension.isRunningInIdea(block: KotlinMultiplatformExtension.() -> Unit) {
 | 
				
			||||||
 | 
					    if (isInIdea()) {
 | 
				
			||||||
 | 
					        block(this)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun KotlinMultiplatformExtension.isNotRunningInIdea(block: KotlinMultiplatformExtension.() -> Unit) {
 | 
				
			||||||
 | 
					    if (!isInIdea()) {
 | 
				
			||||||
 | 
					        block(this)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun KotlinMultiplatformExtension.isRunningInTravis(block: KotlinMultiplatformExtension.() -> Unit) {
 | 
				
			||||||
 | 
					    if (isInTravis()) {
 | 
				
			||||||
 | 
					        block(this)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun KotlinMultiplatformExtension.runningOnLinuxx86_64(block: KotlinMultiplatformExtension.() -> Unit) {
 | 
				
			||||||
 | 
					    if (getHostOsName() == "linux" && getHostArchitecture() == "x86-64") {
 | 
				
			||||||
 | 
					        block(this)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun KotlinMultiplatformExtension.runningOnLinuxArm64(block: KotlinMultiplatformExtension.() -> Unit) {
 | 
				
			||||||
 | 
					    if (getHostOsName() == "linux" && getHostArchitecture() == "aarch64") {
 | 
				
			||||||
 | 
					        block(this)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun KotlinMultiplatformExtension.runningOnLinuxArm32(block: KotlinMultiplatformExtension.() -> Unit) {
 | 
				
			||||||
 | 
					    if (getHostOsName() == "linux" && getHostArchitecture() == "arm-v7") {
 | 
				
			||||||
 | 
					        block(this)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun KotlinMultiplatformExtension.runningOnMacos(block: KotlinMultiplatformExtension.() -> Unit) {
 | 
				
			||||||
 | 
					    if (getHostOsName() == "macos") {
 | 
				
			||||||
 | 
					        block(this)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun KotlinMultiplatformExtension.runningOnWindows(block: KotlinMultiplatformExtension.() -> Unit) {
 | 
				
			||||||
 | 
					    if (getHostOsName() == "windows") {
 | 
				
			||||||
 | 
					        block(this)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun independentDependencyBlock(nativeDeps: KotlinDependencyHandler.() -> Unit): KotlinDependencyHandler.() -> Unit {
 | 
				
			||||||
 | 
					    return nativeDeps
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * On mac when two targets that have the same parent source set have cinterops defined, gradle creates a "common"
 | 
				
			||||||
 | 
					 * target task for that source set metadata, even though it's a native source set, to work around that, we create
 | 
				
			||||||
 | 
					 * an intermediary source set with the same set of dependancies
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					fun NamedDomainObjectContainer<KotlinSourceSet>.createWorkaroundNativeMainSourceSet(
 | 
				
			||||||
 | 
					    name: String,
 | 
				
			||||||
 | 
					    nativeDeps: KotlinDependencyHandler.() -> Unit
 | 
				
			||||||
 | 
					): KotlinSourceSet {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return create("${name}Workaround") {
 | 
				
			||||||
 | 
					        if (!isInIdea()) {
 | 
				
			||||||
 | 
					            kotlin.srcDir("src/nativeMain")
 | 
				
			||||||
 | 
					            dependencies {
 | 
				
			||||||
 | 
					                nativeDeps.invoke(this)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -17,7 +17,9 @@ org.gradle.parallel=true
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
kotlin.code.style=official
 | 
					kotlin.code.style=official
 | 
				
			||||||
 | 
					
 | 
				
			||||||
kotlin.js.compiler=both
 | 
					kotlin.js.compiler=ir
 | 
				
			||||||
kotlin.mpp.enableGranularSourceSetsMetadata=true
 | 
					#kotlin.js.experimental.generateKotlinExternals=true
 | 
				
			||||||
 | 
					#kotlin.mpp.enableGranularSourceSetsMetadata=true
 | 
				
			||||||
 | 
					kotlin.native.disableCompilerDaemon=true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=4096m
 | 
					org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=4096m
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										23
									
								
								linuxBuild.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										23
									
								
								linuxBuild.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@ -1 +1,22 @@
 | 
				
			|||||||
./gradlew build
 | 
					set -e
 | 
				
			||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#this will hopefully download all konan dependancies that we use in the build scripts
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-api:build
 | 
				
			||||||
 | 
					#now let's build linux deps
 | 
				
			||||||
 | 
					export CLANG_BIN=$HOME/.konan/dependencies/clang-llvm-8.0.0-linux-x86-64/bin
 | 
				
			||||||
 | 
					cd sodiumWrapper
 | 
				
			||||||
 | 
					./makeLinuxX86-64.sh
 | 
				
			||||||
 | 
					#Workaround for travis using wrong ld
 | 
				
			||||||
 | 
					if [ "$TRAVIS" = "true" ]
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
					  sudo mv /usr/bin/ld /usr/bin/ld.bck
 | 
				
			||||||
 | 
					  sudo ln -s $CLANG_BIN/ld.lld /usr/bin/ld
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					./makeLinuxArm64.sh
 | 
				
			||||||
 | 
					#now we can do the delegated build
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-delegated:build
 | 
				
			||||||
 | 
					#and finally pure build
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto:build
 | 
				
			||||||
 | 
					set +e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										25
									
								
								linuxBuildAndPublish.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										25
									
								
								linuxBuildAndPublish.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@ -1 +1,24 @@
 | 
				
			|||||||
./gradlew build publishJvmPublicationToSnapshotRepository publishJsPublicationToSnapshotRepository publishKotlinMultiplatformPublicationToSnapshotRepository publishLinuxPublicationToSnapshotRepository publishMetadataPublicationToSnapshotRepository 
 | 
					set -e
 | 
				
			||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#this will hopefully download all konan dependancies that we use in the build scripts
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-api:build
 | 
				
			||||||
 | 
					#now let's build linux deps
 | 
				
			||||||
 | 
					export CLANG_BIN=$HOME/.konan/dependencies/clang-llvm-8.0.0-linux-x86-64/bin
 | 
				
			||||||
 | 
					cd sodiumWrapper
 | 
				
			||||||
 | 
					./makeLinuxX86-64.sh
 | 
				
			||||||
 | 
					#Workaround for travis using wrong ld
 | 
				
			||||||
 | 
					if [ "$TRAVIS" = "true" ]
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
					  sudo mv /usr/bin/ld /usr/bin/ld.bck
 | 
				
			||||||
 | 
					  sudo ln -s $CLANG_BIN/ld.lld /usr/bin/ld
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					./makeLinuxArm64.sh
 | 
				
			||||||
 | 
					#now we can do the delegated build
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-delegated:build
 | 
				
			||||||
 | 
					#and finally pure build
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto:build
 | 
				
			||||||
 | 
					./gradlew publishJvmPublicationToSnapshotRepository publishJsPublicationToSnapshotRepository \
 | 
				
			||||||
 | 
					publishKotlinMultiplatformPublicationToSnapshotRepository publishLinuxX64PublicationToSnapshotRepository \
 | 
				
			||||||
 | 
					publishLinuxArm64PublicationToSnapshotRepository publishMetadataPublicationToSnapshotRepository
 | 
				
			||||||
 | 
					set +e
 | 
				
			||||||
							
								
								
									
										18
									
								
								macBuild-mac-ios.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										18
									
								
								macBuild-mac-ios.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					set -e
 | 
				
			||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#this will hopefully download all konan dependancies that we use in the build scripts
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-api:build
 | 
				
			||||||
 | 
					#now let's build linux deps
 | 
				
			||||||
 | 
					cd sodiumWrapper
 | 
				
			||||||
 | 
					./makeMacosX86-64.sh
 | 
				
			||||||
 | 
					./makeIos.sh
 | 
				
			||||||
 | 
					#now we can do the delegated build of ios and macos libraries
 | 
				
			||||||
 | 
					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 \
 | 
				
			||||||
 | 
					multiplatform-crypto-delegated:macosX64MainKlibrary multiplatform-crypto-delegated:macosX64TestKlibrary
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-delegated:iosX64Test
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-delegated:macosX64Test
 | 
				
			||||||
 | 
					set +e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										5
									
								
								macBuild-pure.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										5
									
								
								macBuild-pure.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					set -e
 | 
				
			||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-api:build
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto:build
 | 
				
			||||||
 | 
					set +e
 | 
				
			||||||
							
								
								
									
										13
									
								
								macBuild-tvos.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										13
									
								
								macBuild-tvos.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					set -e
 | 
				
			||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#this will hopefully download all konan dependancies that we use in the build scripts
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-api:build
 | 
				
			||||||
 | 
					#now let's build linux deps
 | 
				
			||||||
 | 
					cd sodiumWrapper
 | 
				
			||||||
 | 
					./makeTvos.sh
 | 
				
			||||||
 | 
					#now we can do the delegated build of ios and macos libraries
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-delegated:tvosArm64MainKlibrary multiplatform-crypto-delegated:tvosArm64TestKlibrary \
 | 
				
			||||||
 | 
					multiplatform-crypto-delegated:tvosX64MainKlibrary multiplatform-crypto-delegated:tvosX64TestKlibrary
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-delegated:tvosX64Test
 | 
				
			||||||
 | 
					set +e
 | 
				
			||||||
							
								
								
									
										14
									
								
								macBuild-watchos.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										14
									
								
								macBuild-watchos.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					set -e
 | 
				
			||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#this will hopefully download all konan dependancies that we use in the build scripts
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-api:build
 | 
				
			||||||
 | 
					#now let's build linux deps
 | 
				
			||||||
 | 
					cd sodiumWrapper
 | 
				
			||||||
 | 
					./makeWatchos.sh
 | 
				
			||||||
 | 
					#now we can do the delegated build of ios and macos libraries
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					set +e
 | 
				
			||||||
							
								
								
									
										17
									
								
								macBuild.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										17
									
								
								macBuild.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@ -1 +1,16 @@
 | 
				
			|||||||
./gradlew build
 | 
					set -e
 | 
				
			||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#this will hopefully download all konan dependancies that we use in the build scripts
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-api:build
 | 
				
			||||||
 | 
					#now let's build linux deps
 | 
				
			||||||
 | 
					cd sodiumWrapper
 | 
				
			||||||
 | 
					./makeMacosX86-64.sh
 | 
				
			||||||
 | 
					./makeIos.sh
 | 
				
			||||||
 | 
					./makeTvos.sh
 | 
				
			||||||
 | 
					./makeWatchos.sh
 | 
				
			||||||
 | 
					#now we can do the delegated build
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-delegated:build
 | 
				
			||||||
 | 
					#and finally pure build
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto:build
 | 
				
			||||||
 | 
					set +e
 | 
				
			||||||
							
								
								
									
										15
									
								
								macBuildAndPublish-mac-ios.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										15
									
								
								macBuildAndPublish-mac-ios.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					set -e
 | 
				
			||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#this will hopefully download all konan dependancies that we use in the build scripts
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-api:build
 | 
				
			||||||
 | 
					#now let's build linux deps
 | 
				
			||||||
 | 
					cd sodiumWrapper
 | 
				
			||||||
 | 
					./makeMacosX86-64.sh
 | 
				
			||||||
 | 
					./makeIos.sh
 | 
				
			||||||
 | 
					#now we can do the delegated build of ios and macos libraries
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-delegated:publishIosArm32PublicationToSnapshotRepository \
 | 
				
			||||||
 | 
					multiplatform-crypto-delegated:publishIosArm64PublicationToSnapshotRepository \
 | 
				
			||||||
 | 
					multiplatform-crypto-delegated:publishIosX64PublicationToSnapshotRepository \
 | 
				
			||||||
 | 
					multiplatform-crypto-delegated:publishMacosX64PublicationToSnapshotRepository
 | 
				
			||||||
 | 
					set +e
 | 
				
			||||||
							
								
								
									
										14
									
								
								macBuildAndPublish-pure.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										14
									
								
								macBuildAndPublish-pure.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					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 \
 | 
				
			||||||
 | 
					multiplatform-crypto:publishMacosX64PublicationToSnapshotRepository \
 | 
				
			||||||
 | 
					multiplatform-crypto:publishTvosArm64PublicationToSnapshotRepository \
 | 
				
			||||||
 | 
					multiplatform-crypto:publishTvosX64PublicationToSnapshotRepository \
 | 
				
			||||||
 | 
					multiplatform-crypto:publishWatchosArm32PublicationToSnapshotRepository \
 | 
				
			||||||
 | 
					multiplatform-crypto:publishWatchosArm64PublicationToSnapshotRepository \
 | 
				
			||||||
 | 
					multiplatform-crypto:publishWatchosX86PublicationToSnapshotRepository
 | 
				
			||||||
 | 
					set +e
 | 
				
			||||||
							
								
								
									
										12
									
								
								macBuildAndPublish-tvos.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										12
									
								
								macBuildAndPublish-tvos.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					set -e
 | 
				
			||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#this will hopefully download all konan dependancies that we use in the build scripts
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-api:build
 | 
				
			||||||
 | 
					#now let's build linux deps
 | 
				
			||||||
 | 
					cd sodiumWrapper
 | 
				
			||||||
 | 
					./makeTvos.sh
 | 
				
			||||||
 | 
					#now we can do the delegated build of ios and macos libraries
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-delegated:publishTvosArm64PublicationToSnapshotRepository \
 | 
				
			||||||
 | 
					multiplatform-crypto-delegated:publishTvosX64PublicationToSnapshotRepository
 | 
				
			||||||
 | 
					set +e
 | 
				
			||||||
							
								
								
									
										13
									
								
								macBuildAndPublish-watchos.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										13
									
								
								macBuildAndPublish-watchos.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					set -e
 | 
				
			||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#this will hopefully download all konan dependancies that we use in the build scripts
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-api:build
 | 
				
			||||||
 | 
					#now let's build linux deps
 | 
				
			||||||
 | 
					cd sodiumWrapper
 | 
				
			||||||
 | 
					./makeWatchos.sh
 | 
				
			||||||
 | 
					#now we can do the delegated build of ios and macos libraries
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					./gradlew multiplatform-crypto-delegated:publishWatchosArm32PublicationToSnapshotRepository \
 | 
				
			||||||
 | 
					multiplatform-crypto-delegated:publishWatchosArm64PublicationToSnapshotRepository \
 | 
				
			||||||
 | 
					multiplatform-crypto-delegated:publishWatchosX86PublicationToSnapshotRepository
 | 
				
			||||||
 | 
					set +e
 | 
				
			||||||
@ -1 +0,0 @@
 | 
				
			|||||||
./gradlew build publishIos64ArmPublicationToSnapshotRepository publishIosPublicationToSnapshotRepository publishMacosX64PublicationToSnapshotRepository publishIos32ArmPublicationToSnapshotRepository
 | 
					 | 
				
			||||||
@ -1 +0,0 @@
 | 
				
			|||||||
./gradlew publishAllPublicationsToMavenRepository -x publishMetadataPublicationToMavenRepository -x publishKotlinMultiplatformPublicationToMavenRepository
 | 
					 | 
				
			||||||
							
								
								
									
										344
									
								
								multiplatform-crypto-api/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										344
									
								
								multiplatform-crypto-api/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,344 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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.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.dokka) version Versions.dokkaPlugin
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					repositories {
 | 
				
			||||||
 | 
					    mavenCentral()
 | 
				
			||||||
 | 
					    jcenter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					group = ReleaseInfo.group
 | 
				
			||||||
 | 
					version = ReleaseInfo.version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					val ideaActive = System.getProperty("idea.active") == "true"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					kotlin {
 | 
				
			||||||
 | 
					    val hostOsName = getHostOsName()
 | 
				
			||||||
 | 
					    runningOnLinuxx86_64 {
 | 
				
			||||||
 | 
					        jvm()
 | 
				
			||||||
 | 
					        js {
 | 
				
			||||||
 | 
					           browser {
 | 
				
			||||||
 | 
					                testTask {
 | 
				
			||||||
 | 
					                    enabled = false //Until I sort out testing on travis
 | 
				
			||||||
 | 
					                    useKarma {
 | 
				
			||||||
 | 
					                        useChrome()
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            nodejs {
 | 
				
			||||||
 | 
					                testTask {
 | 
				
			||||||
 | 
					                    useMocha() {
 | 
				
			||||||
 | 
					                        timeout = "10s"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        linuxX64("linux") {
 | 
				
			||||||
 | 
					            binaries {
 | 
				
			||||||
 | 
					                staticLib {
 | 
				
			||||||
 | 
					                    optimized = true
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //Not supported in OFFICIAL coroutines at the moment
 | 
				
			||||||
 | 
					        linuxArm64() {
 | 
				
			||||||
 | 
					            binaries {
 | 
				
			||||||
 | 
					                staticLib {
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //Not supported in OFFICAL coroutines at the moment
 | 
				
			||||||
 | 
					        linuxArm32Hfp() {
 | 
				
			||||||
 | 
					            binaries {
 | 
				
			||||||
 | 
					                staticLib {
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runningOnLinuxArm64 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runningOnLinuxArm32 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runningOnMacos {
 | 
				
			||||||
 | 
					        iosX64() {
 | 
				
			||||||
 | 
					            binaries {
 | 
				
			||||||
 | 
					                framework {
 | 
				
			||||||
 | 
					                    optimized = true
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        iosArm64() {
 | 
				
			||||||
 | 
					            binaries {
 | 
				
			||||||
 | 
					                framework {
 | 
				
			||||||
 | 
					                    optimized = true
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        iosArm32() {
 | 
				
			||||||
 | 
					            binaries {
 | 
				
			||||||
 | 
					                framework {
 | 
				
			||||||
 | 
					                    optimized = true
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        macosX64() {
 | 
				
			||||||
 | 
					            binaries {
 | 
				
			||||||
 | 
					                framework {
 | 
				
			||||||
 | 
					                    optimized = true
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        mingwX64() {
 | 
				
			||||||
 | 
					            binaries {
 | 
				
			||||||
 | 
					                staticLib {
 | 
				
			||||||
 | 
					                    optimized = true
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        mingwX86() {
 | 
				
			||||||
 | 
					            binaries {
 | 
				
			||||||
 | 
					                staticLib {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    println(targets.names)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sourceSets {
 | 
				
			||||||
 | 
					        val commonMain by getting {
 | 
				
			||||||
 | 
					            dependencies {
 | 
				
			||||||
 | 
					                implementation(kotlin(Deps.Common.stdLib))
 | 
				
			||||||
 | 
					                implementation(kotlin(Deps.Common.test))
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        val commonTest by getting {
 | 
				
			||||||
 | 
					            dependencies {
 | 
				
			||||||
 | 
					                implementation(kotlin(Deps.Common.test))
 | 
				
			||||||
 | 
					                implementation(kotlin(Deps.Common.testAnnotation))
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        runningOnLinuxx86_64 {
 | 
				
			||||||
 | 
					            val jvmMain by getting {
 | 
				
			||||||
 | 
					                dependencies {
 | 
				
			||||||
 | 
					                    implementation(kotlin(Deps.Jvm.stdLib))
 | 
				
			||||||
 | 
					                    implementation(kotlin(Deps.Jvm.test))
 | 
				
			||||||
 | 
					                    implementation(kotlin(Deps.Jvm.testJUnit))
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            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))
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            val jsTest by getting {
 | 
				
			||||||
 | 
					                dependencies {
 | 
				
			||||||
 | 
					                    implementation(kotlin(Deps.Js.test))
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        runningOnMacos {
 | 
				
			||||||
 | 
					            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)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        all {
 | 
				
			||||||
 | 
					            languageSettings.enableLanguageFeature("InlineClasses")
 | 
				
			||||||
 | 
					            languageSettings.useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
 | 
				
			||||||
 | 
					            languageSettings.useExperimentalAnnotation("kotlin.ExperimentalStdlibApi")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tasks {
 | 
				
			||||||
 | 
					    create<Jar>("javadocJar") {
 | 
				
			||||||
 | 
					        dependsOn(dokka)
 | 
				
			||||||
 | 
					        archiveClassifier.set("javadoc")
 | 
				
			||||||
 | 
					        from(dokka.get().outputDirectory)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dokka {
 | 
				
			||||||
 | 
					        println ("Dokka !")
 | 
				
			||||||
 | 
					        impliedPlatforms = mutableListOf("Common")
 | 
				
			||||||
 | 
					        kotlinTasks {
 | 
				
			||||||
 | 
					            listOf()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        sourceRoot {
 | 
				
			||||||
 | 
					            println ("Common !")
 | 
				
			||||||
 | 
					            path = "/home/ionspin/Projects/Future/kotlin-multiplatform-crypto/crypto/src/commonMain" //TODO remove static path!
 | 
				
			||||||
 | 
					            platforms = listOf("Common")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (getHostOsName() == "linux" && getHostArchitecture() == "x86-64") {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val jvmTest by getting(Test::class) {
 | 
				
			||||||
 | 
					            testLogging {
 | 
				
			||||||
 | 
					                events("PASSED", "FAILED", "SKIPPED")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val linuxTest 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
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 27-May-2020
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					interface CryptoProvider {
 | 
				
			||||||
 | 
					    suspend fun initialize()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					package _multiplatform_crypto_api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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
 | 
				
			||||||
@ -26,25 +26,20 @@ interface Hash {
 | 
				
			|||||||
    val MAX_HASH_BYTES : Int
 | 
					    val MAX_HASH_BYTES : Int
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ExperimentalUnsignedTypes
 | 
					
 | 
				
			||||||
interface UpdatableHash : Hash {
 | 
					interface UpdatableHash : Hash {
 | 
				
			||||||
    fun update(data : Array<UByte>)
 | 
					    fun update(data : UByteArray)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun update(data : String)
 | 
					    fun digest() : UByteArray
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun digest() : Array<UByte>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fun digestString() : String
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ExperimentalUnsignedTypes
 | 
					
 | 
				
			||||||
interface StatelessHash : Hash {
 | 
					interface StatelessHash : Hash {
 | 
				
			||||||
    fun digest(inputString: String, key: String? = null, hashLength: Int = MAX_HASH_BYTES): Array<UByte>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun digest(
 | 
					}
 | 
				
			||||||
        inputMessage: Array<UByte> = emptyArray(),
 | 
					
 | 
				
			||||||
        key: Array<UByte> = emptyArray(),
 | 
					fun String.encodeToUByteArray() : UByteArray{
 | 
				
			||||||
        hashLength: Int = MAX_HASH_BYTES
 | 
					    return encodeToByteArray().toUByteArray()
 | 
				
			||||||
    ): Array<UByte>
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto.hash.blake2b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.hash.StatelessHash
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.hash.UpdatableHash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 24-May-2020
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					object Blake2bProperties {
 | 
				
			||||||
 | 
					    const val MAX_HASH_BYTES = 64
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Blake2b : UpdatableHash {
 | 
				
			||||||
 | 
					    override val MAX_HASH_BYTES: Int
 | 
				
			||||||
 | 
					        get() = Blake2bProperties.MAX_HASH_BYTES
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Blake2bStateless : StatelessHash {
 | 
				
			||||||
 | 
					    override val MAX_HASH_BYTES: Int
 | 
				
			||||||
 | 
					        get() = Blake2bProperties.MAX_HASH_BYTES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun digest(
 | 
				
			||||||
 | 
					        inputMessage: UByteArray = ubyteArrayOf(),
 | 
				
			||||||
 | 
					        key: UByteArray = ubyteArrayOf(),
 | 
				
			||||||
 | 
					        hashLength: Int = MAX_HASH_BYTES
 | 
				
			||||||
 | 
					    ): UByteArray
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto.hash.sha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.hash.StatelessHash
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.hash.UpdatableHash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 24-May-2020
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					object Sha256Properties {
 | 
				
			||||||
 | 
					    const val MAX_HASH_BYTES = 32
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Sha256 : UpdatableHash {
 | 
				
			||||||
 | 
					    override val MAX_HASH_BYTES: Int
 | 
				
			||||||
 | 
					        get() = Sha256Properties.MAX_HASH_BYTES
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					interface StatelessSha256 : StatelessHash {
 | 
				
			||||||
 | 
					    override val MAX_HASH_BYTES: Int
 | 
				
			||||||
 | 
					        get() = Sha256Properties.MAX_HASH_BYTES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun digest(
 | 
				
			||||||
 | 
					        inputMessage: UByteArray = ubyteArrayOf()
 | 
				
			||||||
 | 
					    ): UByteArray
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto.hash.sha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.hash.StatelessHash
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.hash.UpdatableHash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 24-May-2020
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					object Sha512Properties {
 | 
				
			||||||
 | 
					    const val MAX_HASH_BYTES = 64
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					interface Sha512 : UpdatableHash {
 | 
				
			||||||
 | 
					    override val MAX_HASH_BYTES: Int
 | 
				
			||||||
 | 
					        get() = Sha256Properties.MAX_HASH_BYTES
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					interface StatelessSha512 : StatelessHash {
 | 
				
			||||||
 | 
					    override val MAX_HASH_BYTES: Int
 | 
				
			||||||
 | 
					        get() = Sha512Properties.MAX_HASH_BYTES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun digest(
 | 
				
			||||||
 | 
					        inputMessage: UByteArray = ubyteArrayOf()
 | 
				
			||||||
 | 
					    ): UByteArray
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -22,5 +22,5 @@ package com.ionspin.kotlin.crypto.keyderivation
 | 
				
			|||||||
 * on 16-May-2020
 | 
					 * on 16-May-2020
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
interface KeyDerivationFunction {
 | 
					interface KeyDerivationFunction {
 | 
				
			||||||
    fun derive() : Array<UByte>
 | 
					    fun derive() : UByteArray
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										667
									
								
								multiplatform-crypto-delegated/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										667
									
								
								multiplatform-crypto-delegated/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,667 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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) version Versions.dokkaPlugin
 | 
				
			||||||
 | 
					    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 {
 | 
				
			||||||
 | 
					                    isRunningInTravis {
 | 
				
			||||||
 | 
					                        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"
 | 
				
			||||||
 | 
					//                )
 | 
				
			||||||
 | 
					//            }
 | 
				
			||||||
 | 
					//        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Not supported in OFFICIAL coroutines at the moment (we're running a custom build)
 | 
				
			||||||
 | 
					    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.coroutines)
 | 
				
			||||||
 | 
					                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 {
 | 
				
			||||||
 | 
					            implementation(Deps.Native.coroutines)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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 {
 | 
				
			||||||
 | 
					                implementation(Deps.Native.coroutines)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //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 ios64Bit = setOf(
 | 
				
			||||||
 | 
					            "iosArm64", "iosX64"
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        val ios32Bit = setOf(
 | 
				
			||||||
 | 
					            "iosArm32"
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        val mingw64Bit = setOf(
 | 
				
			||||||
 | 
					            "mingwX64"
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val tvos64Bit = setOf(
 | 
				
			||||||
 | 
					            "tvosArm64", "tvosX64"
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val watchos32Bit = setOf(
 | 
				
			||||||
 | 
					            "watchosX86", "watchosArm32", "watchosArm64"
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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 (ios64Bit.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 (ios32Bit.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 (tvos64Bit.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 (watchos32Bit.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"
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            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))
 | 
				
			||||||
 | 
					                    implementation(Deps.Jvm.coroutinesCore)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    //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(Deps.Jvm.coroutinesTest)
 | 
				
			||||||
 | 
					                    implementation(kotlin(Deps.Jvm.reflection))
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            val jsMain by getting {
 | 
				
			||||||
 | 
					                dependencies {
 | 
				
			||||||
 | 
					                    implementation(kotlin(Deps.Js.stdLib))
 | 
				
			||||||
 | 
					                    implementation(Deps.Js.coroutines)
 | 
				
			||||||
 | 
					                    implementation(npm(Deps.Js.Npm.libsodiumWrappers.first, Deps.Js.Npm.libsodiumWrappers.second))
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            val jsTest by getting {
 | 
				
			||||||
 | 
					                dependencies {
 | 
				
			||||||
 | 
					                    implementation(Deps.Js.coroutines)
 | 
				
			||||||
 | 
					                    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(dokka)
 | 
				
			||||||
 | 
					        archiveClassifier.set("javadoc")
 | 
				
			||||||
 | 
					        from(dokka.get().outputDirectory)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dokka {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    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")
 | 
				
			||||||
 | 
					//            }
 | 
				
			||||||
 | 
					//        }
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					//}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								multiplatform-crypto-delegated/libsodium-wrappers-sumo-0.7.6.tgz
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								multiplatform-crypto-delegated/libsodium-wrappers-sumo-0.7.6.tgz
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.sha.*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 24-May-2020
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					object Crypto : CryptoProvider {
 | 
				
			||||||
 | 
					    override suspend fun initialize() {
 | 
				
			||||||
 | 
					        Initializer.initialize()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun initializeWithCallback(done: () -> Unit) {
 | 
				
			||||||
 | 
					        Initializer.initializeWithCallback(done)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    object Blake2b {
 | 
				
			||||||
 | 
					        fun updateable(key: UByteArray? = null, hashLength: Int = Blake2bProperties.MAX_HASH_BYTES): com.ionspin.kotlin.crypto.hash.blake2b.Blake2b {
 | 
				
			||||||
 | 
					            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(): com.ionspin.kotlin.crypto.hash.sha.Sha512 {
 | 
				
			||||||
 | 
					            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()")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					object SimpleCrypto {
 | 
				
			||||||
 | 
					    fun hash(message: String): UByteArray {
 | 
				
			||||||
 | 
					        return ubyteArrayOf(0U)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					expect object Initializer {
 | 
				
			||||||
 | 
					    fun isInitialized() : Boolean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    suspend fun initialize()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun initializeWithCallback(done: () -> (Unit))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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) : Blake2b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					expect object Blake2bDelegatedStateless : Blake2bStateless
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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
 | 
				
			||||||
@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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() : Sha512
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					expect object Sha512StatelessDelegated : StatelessSha512
 | 
				
			||||||
@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -17,13 +17,12 @@
 | 
				
			|||||||
package com.ionspin.kotlin.crypto.symmetric
 | 
					package com.ionspin.kotlin.crypto.symmetric
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.ionspin.kotlin.crypto.SRNG
 | 
					import com.ionspin.kotlin.crypto.SRNG
 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.chunked
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.xor
 | 
					import com.ionspin.kotlin.crypto.util.xor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Advanced encryption standard with cipher block chaining and PKCS #5
 | 
					 * Advanced encryption standard with cipher block chaining and PKCS #5
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * For bulk encryption/decryption use [AesCbc.encrypt] and [AesCbc.decrypt]
 | 
					 * For bulk encryption/decryption use [AesCbcPure.encrypt] and [AesCbcPure.decrypt]
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * To get an instance of AesCbc and then feed it data sequentially with [addData] use [createEncryptor] and [createDecryptor]
 | 
					 * To get an instance of AesCbc and then feed it data sequentially with [addData] use [createEncryptor] and [createDecryptor]
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -31,8 +30,8 @@ import com.ionspin.kotlin.crypto.util.xor
 | 
				
			|||||||
 * ugljesa.jovanovic@ionspin.com
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 * on 21-Sep-2019
 | 
					 * on 21-Sep-2019
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ExperimentalUnsignedTypes
 | 
					
 | 
				
			||||||
class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializationVector: Array<UByte>? = null) {
 | 
					class AesCbcPure internal constructor(val aesKey: AesKey, val mode: Mode, initializationVector: UByteArray? = null) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    companion object {
 | 
					    companion object {
 | 
				
			||||||
        const val BLOCK_BYTES = 16
 | 
					        const val BLOCK_BYTES = 16
 | 
				
			||||||
@ -40,22 +39,22 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
 | 
				
			|||||||
         * Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all
 | 
					         * Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all
 | 
				
			||||||
         * data call [encrypt]
 | 
					         * data call [encrypt]
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        fun createEncryptor(aesKey: AesKey) : AesCbc {
 | 
					        fun createEncryptor(aesKey: AesKey) : AesCbcPure {
 | 
				
			||||||
            return AesCbc(aesKey, Mode.ENCRYPT)
 | 
					            return AesCbcPure(aesKey, Mode.ENCRYPT)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all
 | 
					         * Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all
 | 
				
			||||||
         * data call [decrypt]
 | 
					         * data call [decrypt]
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        fun createDecryptor(aesKey : AesKey) : AesCbc {
 | 
					        fun createDecryptor(aesKey : AesKey) : AesCbcPure {
 | 
				
			||||||
            return AesCbc(aesKey, Mode.DECRYPT)
 | 
					            return AesCbcPure(aesKey, Mode.DECRYPT)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * Bulk encryption, returns encrypted data and a random initialization vector
 | 
					         * Bulk encryption, returns encrypted data and a random initialization vector
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        fun encrypt(aesKey: AesKey, data: Array<UByte>): EncryptedDataAndInitializationVector {
 | 
					        fun encrypt(aesKey: AesKey, data: UByteArray): EncryptedDataAndInitializationVector {
 | 
				
			||||||
            val aesCbc = AesCbc(aesKey, Mode.ENCRYPT)
 | 
					            val aesCbc = AesCbcPure(aesKey, Mode.ENCRYPT)
 | 
				
			||||||
            aesCbc.addData(data)
 | 
					            aesCbc.addData(data)
 | 
				
			||||||
            return aesCbc.encrypt()
 | 
					            return aesCbc.encrypt()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -63,20 +62,20 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
 | 
				
			|||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * Bulk decryption, returns decrypted data
 | 
					         * Bulk decryption, returns decrypted data
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        fun decrypt(aesKey: AesKey, data: Array<UByte>, initialCounter: Array<UByte>? = null): Array<UByte> {
 | 
					        fun decrypt(aesKey: AesKey, data: UByteArray, initialCounter: UByteArray? = null): UByteArray {
 | 
				
			||||||
            val aesCbc = AesCbc(aesKey, Mode.DECRYPT, initialCounter)
 | 
					            val aesCbc = AesCbcPure(aesKey, Mode.DECRYPT, initialCounter)
 | 
				
			||||||
            aesCbc.addData(data)
 | 
					            aesCbc.addData(data)
 | 
				
			||||||
            return aesCbc.decrypt()
 | 
					            return aesCbc.decrypt()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun padToBlock(unpadded: Array<UByte>): Array<UByte> {
 | 
					        private fun padToBlock(unpadded: UByteArray): UByteArray {
 | 
				
			||||||
            val paddingSize = 16 - unpadded.size
 | 
					            val paddingSize = 16 - unpadded.size
 | 
				
			||||||
            if (unpadded.size == BLOCK_BYTES) {
 | 
					            if (unpadded.size == BLOCK_BYTES) {
 | 
				
			||||||
                return unpadded
 | 
					                return unpadded
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (unpadded.size == BLOCK_BYTES) {
 | 
					            if (unpadded.size == BLOCK_BYTES) {
 | 
				
			||||||
                return Array(BLOCK_BYTES) {
 | 
					                return UByteArray(BLOCK_BYTES) {
 | 
				
			||||||
                    BLOCK_BYTES.toUByte()
 | 
					                    BLOCK_BYTES.toUByte()
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -85,7 +84,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
 | 
				
			|||||||
                throw IllegalStateException("Block larger than 128 bytes")
 | 
					                throw IllegalStateException("Block larger than 128 bytes")
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return Array(BLOCK_BYTES) {
 | 
					            return UByteArray(BLOCK_BYTES) {
 | 
				
			||||||
                when (it) {
 | 
					                when (it) {
 | 
				
			||||||
                    in unpadded.indices -> unpadded[it]
 | 
					                    in unpadded.indices -> unpadded[it]
 | 
				
			||||||
                    else -> paddingSize.toUByte()
 | 
					                    else -> paddingSize.toUByte()
 | 
				
			||||||
@ -95,20 +94,20 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var currentOutput: Array<UByte> = arrayOf()
 | 
					    var currentOutput: UByteArray = ubyteArrayOf()
 | 
				
			||||||
    var previousEncrypted: Array<UByte> = arrayOf()
 | 
					    var previousEncrypted: UByteArray = ubyteArrayOf()
 | 
				
			||||||
    val initVector = if (initializationVector.isNullOrEmpty()) {
 | 
					    val initVector = if (initializationVector.isNullOrEmpty()) {
 | 
				
			||||||
        SRNG.getRandomBytes(16)
 | 
					        SRNG.getRandomBytes(16)
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        initializationVector
 | 
					        initializationVector
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val output = MutableList<Array<UByte>>(0) { arrayOf() }
 | 
					    val output = MutableList<UByteArray>(0) { ubyteArrayOf() }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var buffer: Array<UByte> = UByteArray(16) { 0U }.toTypedArray()
 | 
					    var buffer: UByteArray = UByteArray(16) { 0U }
 | 
				
			||||||
    var bufferCounter = 0
 | 
					    var bufferCounter = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun addData(data: Array<UByte>) {
 | 
					    fun addData(data: UByteArray) {
 | 
				
			||||||
        //Padding
 | 
					        //Padding
 | 
				
			||||||
        when {
 | 
					        when {
 | 
				
			||||||
            bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
 | 
					            bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
 | 
				
			||||||
@ -116,16 +115,16 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
 | 
				
			|||||||
                val chunked = data.chunked(BLOCK_BYTES)
 | 
					                val chunked = data.chunked(BLOCK_BYTES)
 | 
				
			||||||
                chunked.forEach { chunk ->
 | 
					                chunked.forEach { chunk ->
 | 
				
			||||||
                    if (bufferCounter + chunk.size < BLOCK_BYTES) {
 | 
					                    if (bufferCounter + chunk.size < BLOCK_BYTES) {
 | 
				
			||||||
                        appendToBuffer(chunk, bufferCounter)
 | 
					                        appendToBuffer(chunk.toUByteArray(), bufferCounter)
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        chunk.copyInto(
 | 
					                        chunk.toUByteArray().copyInto(
 | 
				
			||||||
                            destination = buffer,
 | 
					                            destination = buffer,
 | 
				
			||||||
                            destinationOffset = bufferCounter,
 | 
					                            destinationOffset = bufferCounter,
 | 
				
			||||||
                            startIndex = 0,
 | 
					                            startIndex = 0,
 | 
				
			||||||
                            endIndex = BLOCK_BYTES - bufferCounter
 | 
					                            endIndex = BLOCK_BYTES - bufferCounter
 | 
				
			||||||
                        )
 | 
					                        )
 | 
				
			||||||
                        output += consumeBlock(buffer)
 | 
					                        output += consumeBlock(buffer)
 | 
				
			||||||
                        buffer = Array<UByte>(BLOCK_BYTES) {
 | 
					                        buffer = UByteArray(BLOCK_BYTES) {
 | 
				
			||||||
                            when (it) {
 | 
					                            when (it) {
 | 
				
			||||||
                                in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> {
 | 
					                                in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> {
 | 
				
			||||||
                                    chunk[it + (BLOCK_BYTES - bufferCounter)]
 | 
					                                    chunk[it + (BLOCK_BYTES - bufferCounter)]
 | 
				
			||||||
@ -153,7 +152,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
 | 
				
			|||||||
        if (bufferCounter > 0) {
 | 
					        if (bufferCounter > 0) {
 | 
				
			||||||
            val lastBlockPadded = padToBlock(buffer)
 | 
					            val lastBlockPadded = padToBlock(buffer)
 | 
				
			||||||
            if (lastBlockPadded.size > BLOCK_BYTES) {
 | 
					            if (lastBlockPadded.size > BLOCK_BYTES) {
 | 
				
			||||||
                val chunks = lastBlockPadded.chunked(BLOCK_BYTES)
 | 
					                val chunks = lastBlockPadded.chunked(BLOCK_BYTES).map { it.toUByteArray() }
 | 
				
			||||||
                output += consumeBlock(chunks[0])
 | 
					                output += consumeBlock(chunks[0])
 | 
				
			||||||
                output += consumeBlock(chunks[1])
 | 
					                output += consumeBlock(chunks[1])
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
@ -161,7 +160,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return EncryptedDataAndInitializationVector(
 | 
					        return EncryptedDataAndInitializationVector(
 | 
				
			||||||
            output.reversed().foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes },
 | 
					            output.reversed().foldRight(UByteArray(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes },
 | 
				
			||||||
            initVector
 | 
					            initVector
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -170,7 +169,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
 | 
				
			|||||||
     * Decrypt data
 | 
					     * Decrypt data
 | 
				
			||||||
     * @return Decrypted data
 | 
					     * @return Decrypted data
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    fun decrypt(): Array<UByte> {
 | 
					    fun decrypt(): UByteArray {
 | 
				
			||||||
        val removePaddingCount = output.last().last()
 | 
					        val removePaddingCount = output.last().last()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -178,37 +177,38 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
 | 
				
			|||||||
            output.last().dropLast(removePaddingCount.toInt() and 0x7F)
 | 
					            output.last().dropLast(removePaddingCount.toInt() and 0x7F)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            output.last().toList()
 | 
					            output.last().toList()
 | 
				
			||||||
        }
 | 
					        }.toUByteArray()
 | 
				
			||||||
        val preparedOutput = output.dropLast(1).toTypedArray() + removedPadding.toTypedArray()
 | 
					        val preparedOutput = (output.dropLast(1) + listOf(removedPadding))
 | 
				
			||||||
        //JS compiler freaks out here if we don't supply exact type
 | 
					        //JS compiler freaks out here if we don't supply exact type
 | 
				
			||||||
        val reversed : List<Array<UByte>> = preparedOutput.reversed() as List<Array<UByte>>
 | 
					        val reversed : List<UByteArray> = preparedOutput.reversed() as List<UByteArray>
 | 
				
			||||||
        val folded : Array<UByte> = reversed.foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc ->
 | 
					        val folded : UByteArray = reversed.foldRight(UByteArray(0) { 0U }) { uByteArray, acc ->
 | 
				
			||||||
            acc + arrayOfUBytes }
 | 
					            acc + uByteArray
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        return folded
 | 
					        return folded
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun appendToBuffer(array: Array<UByte>, start: Int) {
 | 
					    private fun appendToBuffer(array: UByteArray, start: Int) {
 | 
				
			||||||
        array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
 | 
					        array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
 | 
				
			||||||
        bufferCounter += array.size
 | 
					        bufferCounter += array.size
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun consumeBlock(data: Array<UByte>): Array<UByte> {
 | 
					    private fun consumeBlock(data: UByteArray): UByteArray {
 | 
				
			||||||
        return when (mode) {
 | 
					        return when (mode) {
 | 
				
			||||||
            Mode.ENCRYPT -> {
 | 
					            Mode.ENCRYPT -> {
 | 
				
			||||||
                currentOutput = if (currentOutput.isEmpty()) {
 | 
					                currentOutput = if (currentOutput.isEmpty()) {
 | 
				
			||||||
                    println("IV: $initVector")
 | 
					                    println("IV: $initVector")
 | 
				
			||||||
                    Aes.encrypt(aesKey, data xor initVector)
 | 
					                    AesPure.encrypt(aesKey, data xor initVector)
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    Aes.encrypt(aesKey, data xor currentOutput)
 | 
					                    AesPure.encrypt(aesKey, data xor currentOutput)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                currentOutput
 | 
					                currentOutput
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Mode.DECRYPT -> {
 | 
					            Mode.DECRYPT -> {
 | 
				
			||||||
                if (currentOutput.isEmpty()) {
 | 
					                if (currentOutput.isEmpty()) {
 | 
				
			||||||
                    currentOutput = Aes.decrypt(aesKey, data) xor initVector
 | 
					                    currentOutput = AesPure.decrypt(aesKey, data) xor initVector
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    currentOutput = Aes.decrypt(aesKey, data) xor previousEncrypted
 | 
					                    currentOutput = AesPure.decrypt(aesKey, data) xor previousEncrypted
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                previousEncrypted = data
 | 
					                previousEncrypted = data
 | 
				
			||||||
                currentOutput
 | 
					                currentOutput
 | 
				
			||||||
@ -219,8 +219,8 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ExperimentalUnsignedTypes
 | 
					
 | 
				
			||||||
data class EncryptedDataAndInitializationVector(val encryptedData : Array<UByte>, val initilizationVector : Array<UByte>) {
 | 
					data class EncryptedDataAndInitializationVector(val encryptedData : UByteArray, val initilizationVector : UByteArray) {
 | 
				
			||||||
    override fun equals(other: Any?): Boolean {
 | 
					    override fun equals(other: Any?): Boolean {
 | 
				
			||||||
        if (this === other) return true
 | 
					        if (this === other) return true
 | 
				
			||||||
        if (other == null || this::class != other::class) return false
 | 
					        if (other == null || this::class != other::class) return false
 | 
				
			||||||
@ -20,15 +20,14 @@ import com.ionspin.kotlin.bignum.Endianness
 | 
				
			|||||||
import com.ionspin.kotlin.bignum.integer.BigInteger
 | 
					import com.ionspin.kotlin.bignum.integer.BigInteger
 | 
				
			||||||
import com.ionspin.kotlin.bignum.modular.ModularBigInteger
 | 
					import com.ionspin.kotlin.bignum.modular.ModularBigInteger
 | 
				
			||||||
import com.ionspin.kotlin.crypto.SRNG
 | 
					import com.ionspin.kotlin.crypto.SRNG
 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.chunked
 | 
					import com.ionspin.kotlin.crypto.symmetric.AesCtrPure.Companion.encrypt
 | 
				
			||||||
import com.ionspin.kotlin.crypto.symmetric.AesCtr.Companion.encrypt
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.xor
 | 
					import com.ionspin.kotlin.crypto.util.xor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *  Advanced encryption standard with counter mode
 | 
					 *  Advanced encryption standard with counter mode
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * For bulk encryption/decryption use [AesCtr.encrypt] and [AesCtr.decrypt]
 | 
					 * For bulk encryption/decryption use [AesCtrPure.encrypt] and [AesCtrPure.decrypt]
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * To get an instance of AesCtr and then feed it data sequentially with [addData] use [createEncryptor] and [createDecryptor]
 | 
					 * To get an instance of AesCtr and then feed it data sequentially with [addData] use [createEncryptor] and [createDecryptor]
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -36,8 +35,8 @@ import com.ionspin.kotlin.crypto.util.xor
 | 
				
			|||||||
 * ugljesa.jovanovic@ionspin.com
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 * on 22-Sep-2019
 | 
					 * on 22-Sep-2019
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ExperimentalUnsignedTypes
 | 
					
 | 
				
			||||||
class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCounter: Array<UByte>? = null) {
 | 
					class AesCtrPure internal constructor(val aesKey: AesKey, val mode: Mode, initialCounter: UByteArray? = null) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    companion object {
 | 
					    companion object {
 | 
				
			||||||
        const val BLOCK_BYTES = 16
 | 
					        const val BLOCK_BYTES = 16
 | 
				
			||||||
@ -47,50 +46,50 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
 | 
				
			|||||||
         * Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all
 | 
					         * Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all
 | 
				
			||||||
         * data call [encrypt]
 | 
					         * data call [encrypt]
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        fun createEncryptor(aesKey: AesKey) : AesCtr {
 | 
					        fun createEncryptor(aesKey: AesKey) : AesCtrPure {
 | 
				
			||||||
            return AesCtr(aesKey, Mode.ENCRYPT)
 | 
					            return AesCtrPure(aesKey, Mode.ENCRYPT)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all
 | 
					         * Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all
 | 
				
			||||||
         * data call [decrypt]
 | 
					         * data call [decrypt]
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        fun createDecryptor(aesKey : AesKey) : AesCtr {
 | 
					        fun createDecryptor(aesKey : AesKey) : AesCtrPure {
 | 
				
			||||||
            return AesCtr(aesKey, Mode.DECRYPT)
 | 
					            return AesCtrPure(aesKey, Mode.DECRYPT)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * Bulk encryption, returns encrypted data and a random initial counter 
 | 
					         * Bulk encryption, returns encrypted data and a random initial counter 
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        fun encrypt(aesKey: AesKey, data: Array<UByte>): EncryptedDataAndInitialCounter {
 | 
					        fun encrypt(aesKey: AesKey, data: UByteArray): EncryptedDataAndInitialCounter {
 | 
				
			||||||
            val aesCtr = AesCtr(aesKey, Mode.ENCRYPT)
 | 
					            val aesCtr = AesCtrPure(aesKey, Mode.ENCRYPT)
 | 
				
			||||||
            aesCtr.addData(data)
 | 
					            aesCtr.addData(data)
 | 
				
			||||||
            return aesCtr.encrypt()
 | 
					            return aesCtr.encrypt()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * Bulk decryption, returns decrypted data
 | 
					         * Bulk decryption, returns decrypted data
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        fun decrypt(aesKey: AesKey, data: Array<UByte>, initialCounter: Array<UByte>? = null): Array<UByte> {
 | 
					        fun decrypt(aesKey: AesKey, data: UByteArray, initialCounter: UByteArray? = null): UByteArray {
 | 
				
			||||||
            val aesCtr = AesCtr(aesKey, Mode.DECRYPT, initialCounter)
 | 
					            val aesCtr = AesCtrPure(aesKey, Mode.DECRYPT, initialCounter)
 | 
				
			||||||
            aesCtr.addData(data)
 | 
					            aesCtr.addData(data)
 | 
				
			||||||
            return aesCtr.decrypt()
 | 
					            return aesCtr.decrypt()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var currentOutput: Array<UByte> = arrayOf()
 | 
					    var currentOutput: UByteArray = ubyteArrayOf()
 | 
				
			||||||
    var previousEncrypted: Array<UByte> = arrayOf()
 | 
					    var previousEncrypted: UByteArray = ubyteArrayOf()
 | 
				
			||||||
    val counterStart = if (initialCounter.isNullOrEmpty()) {
 | 
					    val counterStart = if (initialCounter.isNullOrEmpty()) {
 | 
				
			||||||
        SRNG.getRandomBytes(16)
 | 
					        SRNG.getRandomBytes(16)
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        initialCounter
 | 
					        initialCounter
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    var blockCounter = modularCreator.fromBigInteger(BigInteger.fromUByteArray(counterStart, Endianness.BIG))
 | 
					    var blockCounter = modularCreator.fromBigInteger(BigInteger.fromUByteArray(counterStart.toTypedArray(), Endianness.BIG))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val output = MutableList<Array<UByte>>(0) { arrayOf() }
 | 
					    val output = MutableList<UByteArray>(0) { ubyteArrayOf() }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var buffer: Array<UByte> = UByteArray(16) { 0U }.toTypedArray()
 | 
					    var buffer: UByteArray = UByteArray(16) { 0U }
 | 
				
			||||||
    var bufferCounter = 0
 | 
					    var bufferCounter = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun addData(data: Array<UByte>) {
 | 
					    fun addData(data: UByteArray) {
 | 
				
			||||||
        //Padding
 | 
					        //Padding
 | 
				
			||||||
        when {
 | 
					        when {
 | 
				
			||||||
            bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
 | 
					            bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
 | 
				
			||||||
@ -98,9 +97,9 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
 | 
				
			|||||||
                val chunked = data.chunked(BLOCK_BYTES)
 | 
					                val chunked = data.chunked(BLOCK_BYTES)
 | 
				
			||||||
                chunked.forEach { chunk ->
 | 
					                chunked.forEach { chunk ->
 | 
				
			||||||
                    if (bufferCounter + chunk.size < BLOCK_BYTES) {
 | 
					                    if (bufferCounter + chunk.size < BLOCK_BYTES) {
 | 
				
			||||||
                        appendToBuffer(chunk, bufferCounter)
 | 
					                        appendToBuffer(chunk.toUByteArray(), bufferCounter)
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        chunk.copyInto(
 | 
					                        chunk.toUByteArray().copyInto(
 | 
				
			||||||
                            destination = buffer,
 | 
					                            destination = buffer,
 | 
				
			||||||
                            destinationOffset = bufferCounter,
 | 
					                            destinationOffset = bufferCounter,
 | 
				
			||||||
                            startIndex = 0,
 | 
					                            startIndex = 0,
 | 
				
			||||||
@ -108,7 +107,7 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
 | 
				
			|||||||
                        )
 | 
					                        )
 | 
				
			||||||
                        output += consumeBlock(buffer, blockCounter)
 | 
					                        output += consumeBlock(buffer, blockCounter)
 | 
				
			||||||
                        blockCounter += 1
 | 
					                        blockCounter += 1
 | 
				
			||||||
                        buffer = Array<UByte>(BLOCK_BYTES) {
 | 
					                        buffer = UByteArray(BLOCK_BYTES) {
 | 
				
			||||||
                            when (it) {
 | 
					                            when (it) {
 | 
				
			||||||
                                in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> {
 | 
					                                in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> {
 | 
				
			||||||
                                    chunk[it + (BLOCK_BYTES - bufferCounter)]
 | 
					                                    chunk[it + (BLOCK_BYTES - bufferCounter)]
 | 
				
			||||||
@ -136,7 +135,7 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
 | 
				
			|||||||
            output += consumeBlock(buffer, blockCounter)
 | 
					            output += consumeBlock(buffer, blockCounter)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return EncryptedDataAndInitialCounter(
 | 
					        return EncryptedDataAndInitialCounter(
 | 
				
			||||||
            output.reversed().foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes },
 | 
					            output.reversed().foldRight(UByteArray(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes },
 | 
				
			||||||
            counterStart
 | 
					            counterStart
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -144,41 +143,41 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
 | 
				
			|||||||
     * Decrypt data
 | 
					     * Decrypt data
 | 
				
			||||||
     * @return Decrypted data
 | 
					     * @return Decrypted data
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    fun decrypt(): Array<UByte> {
 | 
					    fun decrypt(): UByteArray {
 | 
				
			||||||
        if (bufferCounter > 0) {
 | 
					        if (bufferCounter > 0) {
 | 
				
			||||||
            output += consumeBlock(buffer, blockCounter)
 | 
					            output += consumeBlock(buffer, blockCounter)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        //JS compiler freaks out here if we don't supply exact type
 | 
					        //JS compiler freaks out here if we don't supply exact type
 | 
				
			||||||
        val reversed: List<Array<UByte>> = output.reversed() as List<Array<UByte>>
 | 
					        val reversed: List<UByteArray> = output.reversed() as List<UByteArray>
 | 
				
			||||||
        val folded: Array<UByte> = reversed.foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc ->
 | 
					        val folded: UByteArray = reversed.foldRight(UByteArray(0) { 0U }) { arrayOfUBytes, acc ->
 | 
				
			||||||
            acc + arrayOfUBytes
 | 
					            acc + arrayOfUBytes
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return folded
 | 
					        return folded
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun appendToBuffer(array: Array<UByte>, start: Int) {
 | 
					    private fun appendToBuffer(array: UByteArray, start: Int) {
 | 
				
			||||||
        array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
 | 
					        array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
 | 
				
			||||||
        bufferCounter += array.size
 | 
					        bufferCounter += array.size
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun consumeBlock(data: Array<UByte>, blockCount: ModularBigInteger): Array<UByte> {
 | 
					    private fun consumeBlock(data: UByteArray, blockCount: ModularBigInteger): UByteArray {
 | 
				
			||||||
        val blockCountAsByteArray = blockCount.toUByteArray(Endianness.BIG).expandCounterTo16Bytes()
 | 
					        val blockCountAsByteArray = blockCount.toUByteArray(Endianness.BIG).toUByteArray().expandCounterTo16Bytes()
 | 
				
			||||||
        return when (mode) {
 | 
					        return when (mode) {
 | 
				
			||||||
            Mode.ENCRYPT -> {
 | 
					            Mode.ENCRYPT -> {
 | 
				
			||||||
                Aes.encrypt(aesKey, blockCountAsByteArray) xor data
 | 
					                AesPure.encrypt(aesKey, blockCountAsByteArray) xor data
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Mode.DECRYPT -> {
 | 
					            Mode.DECRYPT -> {
 | 
				
			||||||
                Aes.encrypt(aesKey, blockCountAsByteArray) xor data
 | 
					                AesPure.encrypt(aesKey, blockCountAsByteArray) xor data
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun Array<UByte>.expandCounterTo16Bytes() : Array<UByte> {
 | 
					    private fun UByteArray.expandCounterTo16Bytes() : UByteArray {
 | 
				
			||||||
        return if (this.size < 16) {
 | 
					        return if (this.size < 16) {
 | 
				
			||||||
            println("Expanding")
 | 
					            println("Expanding")
 | 
				
			||||||
            val diff = 16 - this.size
 | 
					            val diff = 16 - this.size
 | 
				
			||||||
            val pad = Array<UByte>(diff) { 0U }
 | 
					            val pad = UByteArray(diff) { 0U }
 | 
				
			||||||
            pad + this
 | 
					            pad + this
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            this
 | 
					            this
 | 
				
			||||||
@ -187,8 +186,8 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ExperimentalUnsignedTypes
 | 
					
 | 
				
			||||||
data class EncryptedDataAndInitialCounter(val encryptedData : Array<UByte>, val initialCounter : Array<UByte>) {
 | 
					data class EncryptedDataAndInitialCounter(val encryptedData : UByteArray, val initialCounter : UByteArray) {
 | 
				
			||||||
    override fun equals(other: Any?): Boolean {
 | 
					    override fun equals(other: Any?): Boolean {
 | 
				
			||||||
        if (this === other) return true
 | 
					        if (this === other) return true
 | 
				
			||||||
        if (other == null || this::class != other::class) return false
 | 
					        if (other == null || this::class != other::class) return false
 | 
				
			||||||
@ -1,10 +1,12 @@
 | 
				
			|||||||
package com.ionspin.kotlin.crypto.symmetric
 | 
					package com.ionspin.kotlin.crypto.symmetric
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.util.flattenToUByteArray
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Created by Ugljesa Jovanovic (jovanovic.ugljesa@gmail.com) on 07/Sep/2019
 | 
					 * Created by Ugljesa Jovanovic (jovanovic.ugljesa@gmail.com) on 07/Sep/2019
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ExperimentalUnsignedTypes
 | 
					
 | 
				
			||||||
internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UByte>) {
 | 
					internal class AesPure internal constructor(val aesKey: AesKey, val input: UByteArray) {
 | 
				
			||||||
    companion object {
 | 
					    companion object {
 | 
				
			||||||
        private val debug = false
 | 
					        private val debug = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -54,18 +56,18 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        val rcon: UByteArray = ubyteArrayOf(0x8DU, 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, 0x1BU, 0x36U)
 | 
					        val rcon: UByteArray = ubyteArrayOf(0x8DU, 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, 0x1BU, 0x36U)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fun encrypt(aesKey: AesKey, input: Array<UByte>): Array<UByte> {
 | 
					        fun encrypt(aesKey: AesKey, input: UByteArray): UByteArray {
 | 
				
			||||||
            return Aes(aesKey, input).encrypt()
 | 
					            return AesPure(aesKey, input).encrypt()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fun decrypt(aesKey: AesKey, input: Array<UByte>): Array<UByte> {
 | 
					        fun decrypt(aesKey: AesKey, input: UByteArray): UByteArray {
 | 
				
			||||||
            return Aes(aesKey, input).decrypt()
 | 
					            return AesPure(aesKey, input).decrypt()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val state: Array<Array<UByte>> = (0 until 4).map { outerCounter ->
 | 
					    val state: Array<UByteArray> = (0 until 4).map { outerCounter ->
 | 
				
			||||||
        Array<UByte>(4) { innerCounter -> input[innerCounter * 4 + outerCounter] }
 | 
					        UByteArray(4) { innerCounter -> input[innerCounter * 4 + outerCounter] }
 | 
				
			||||||
    }.toTypedArray()
 | 
					    }.toTypedArray()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val numberOfRounds = when (aesKey) {
 | 
					    val numberOfRounds = when (aesKey) {
 | 
				
			||||||
@ -74,7 +76,7 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
 | 
				
			|||||||
        is AesKey.Aes256Key -> 14
 | 
					        is AesKey.Aes256Key -> 14
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val expandedKey: Array<Array<UByte>> = expandKey()
 | 
					    val expandedKey: Array<UByteArray> = expandKey()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var round = 0
 | 
					    var round = 0
 | 
				
			||||||
@ -110,22 +112,22 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun shiftRows() {
 | 
					    fun shiftRows() {
 | 
				
			||||||
        state[0] = arrayOf(state[0][0], state[0][1], state[0][2], state[0][3])
 | 
					        state[0] = ubyteArrayOf(state[0][0], state[0][1], state[0][2], state[0][3])
 | 
				
			||||||
        state[1] = arrayOf(state[1][1], state[1][2], state[1][3], state[1][0])
 | 
					        state[1] = ubyteArrayOf(state[1][1], state[1][2], state[1][3], state[1][0])
 | 
				
			||||||
        state[2] = arrayOf(state[2][2], state[2][3], state[2][0], state[2][1])
 | 
					        state[2] = ubyteArrayOf(state[2][2], state[2][3], state[2][0], state[2][1])
 | 
				
			||||||
        state[3] = arrayOf(state[3][3], state[3][0], state[3][1], state[3][2])
 | 
					        state[3] = ubyteArrayOf(state[3][3], state[3][0], state[3][1], state[3][2])
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun inversShiftRows() {
 | 
					    fun inversShiftRows() {
 | 
				
			||||||
        state[0] = arrayOf(state[0][0], state[0][1], state[0][2], state[0][3])
 | 
					        state[0] = ubyteArrayOf(state[0][0], state[0][1], state[0][2], state[0][3])
 | 
				
			||||||
        state[1] = arrayOf(state[1][3], state[1][0], state[1][1], state[1][2])
 | 
					        state[1] = ubyteArrayOf(state[1][3], state[1][0], state[1][1], state[1][2])
 | 
				
			||||||
        state[2] = arrayOf(state[2][2], state[2][3], state[2][0], state[2][1])
 | 
					        state[2] = ubyteArrayOf(state[2][2], state[2][3], state[2][0], state[2][1])
 | 
				
			||||||
        state[3] = arrayOf(state[3][1], state[3][2], state[3][3], state[3][0])
 | 
					        state[3] = ubyteArrayOf(state[3][1], state[3][2], state[3][3], state[3][0])
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun mixColumns() {
 | 
					    fun mixColumns() {
 | 
				
			||||||
        val stateMixed: Array<Array<UByte>> = (0 until 4).map {
 | 
					        val stateMixed: Array<UByteArray> = (0 until 4).map {
 | 
				
			||||||
            Array<UByte>(4) { 0U }
 | 
					            UByteArray(4) { 0U }
 | 
				
			||||||
        }.toTypedArray()
 | 
					        }.toTypedArray()
 | 
				
			||||||
        for (c in 0..3) {
 | 
					        for (c in 0..3) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -138,8 +140,8 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun inverseMixColumns() {
 | 
					    fun inverseMixColumns() {
 | 
				
			||||||
        val stateMixed: Array<Array<UByte>> = (0 until 4).map {
 | 
					        val stateMixed: Array<UByteArray> = (0 until 4).map {
 | 
				
			||||||
            Array<UByte>(4) { 0U }
 | 
					            UByteArray(4) { 0U }
 | 
				
			||||||
        }.toTypedArray()
 | 
					        }.toTypedArray()
 | 
				
			||||||
        for (c in 0..3) {
 | 
					        for (c in 0..3) {
 | 
				
			||||||
            stateMixed[0][c] =
 | 
					            stateMixed[0][c] =
 | 
				
			||||||
@ -203,9 +205,9 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
 | 
				
			|||||||
        return galoisFieldMultiply(this.toUByte(), second)
 | 
					        return galoisFieldMultiply(this.toUByte(), second)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun expandKey(): Array<Array<UByte>> {
 | 
					    fun expandKey(): Array<UByteArray> {
 | 
				
			||||||
        val expandedKey = (0 until 4 * (numberOfRounds + 1)).map {
 | 
					        val expandedKey = (0 until 4 * (numberOfRounds + 1)).map {
 | 
				
			||||||
            Array<UByte>(4) { 0U }
 | 
					            UByteArray(4) { 0U }
 | 
				
			||||||
        }.toTypedArray()
 | 
					        }.toTypedArray()
 | 
				
			||||||
        // First round
 | 
					        // First round
 | 
				
			||||||
        for (i in 0 until aesKey.numberOf32BitWords) {
 | 
					        for (i in 0 until aesKey.numberOf32BitWords) {
 | 
				
			||||||
@ -241,13 +243,13 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            expandedKey[i] = expandedKey[i - aesKey.numberOf32BitWords].mapIndexed { index, it ->
 | 
					            expandedKey[i] = expandedKey[i - aesKey.numberOf32BitWords].mapIndexed { index, it ->
 | 
				
			||||||
                it xor temp[index]
 | 
					                it xor temp[index]
 | 
				
			||||||
            }.toTypedArray()
 | 
					            }.toUByteArray()
 | 
				
			||||||
            clearArray(temp)
 | 
					            clearArray(temp)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return expandedKey
 | 
					        return expandedKey
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun encrypt(): Array<UByte> {
 | 
					    fun encrypt(): UByteArray {
 | 
				
			||||||
        if (completed) {
 | 
					        if (completed) {
 | 
				
			||||||
            throw RuntimeException("Encrypt can only be called once per Aes instance, since the state is cleared at the " +
 | 
					            throw RuntimeException("Encrypt can only be called once per Aes instance, since the state is cleared at the " +
 | 
				
			||||||
                    "end of the operation")
 | 
					                    "end of the operation")
 | 
				
			||||||
@ -273,8 +275,8 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
 | 
				
			|||||||
        addRoundKey()
 | 
					        addRoundKey()
 | 
				
			||||||
        printState()
 | 
					        printState()
 | 
				
			||||||
        val transposedMatrix = (0 until 4).map { outerCounter ->
 | 
					        val transposedMatrix = (0 until 4).map { outerCounter ->
 | 
				
			||||||
            Array<UByte>(4) { 0U }
 | 
					            UByteArray(4) { 0U }
 | 
				
			||||||
        }.toTypedArray()
 | 
					        }
 | 
				
			||||||
        for (i in 0 until 4) {
 | 
					        for (i in 0 until 4) {
 | 
				
			||||||
            for (j in 0 until 4) {
 | 
					            for (j in 0 until 4) {
 | 
				
			||||||
                transposedMatrix[i][j] = state[j][i]
 | 
					                transposedMatrix[i][j] = state[j][i]
 | 
				
			||||||
@ -282,10 +284,10 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        state.forEach { clearArray(it) }
 | 
					        state.forEach { clearArray(it) }
 | 
				
			||||||
        completed = true
 | 
					        completed = true
 | 
				
			||||||
        return transposedMatrix.flatten().toTypedArray()
 | 
					        return transposedMatrix.flattenToUByteArray()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun decrypt(): Array<UByte> {
 | 
					    fun decrypt(): UByteArray {
 | 
				
			||||||
        if (completed) {
 | 
					        if (completed) {
 | 
				
			||||||
            throw RuntimeException("Decrypt can only be called once per Aes instance, since the state is cleared at the " +
 | 
					            throw RuntimeException("Decrypt can only be called once per Aes instance, since the state is cleared at the " +
 | 
				
			||||||
                    "end of the operation")
 | 
					                    "end of the operation")
 | 
				
			||||||
@ -313,20 +315,19 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
 | 
				
			|||||||
        printState()
 | 
					        printState()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val transposedMatrix =  (0 until 4).map { outerCounter ->
 | 
					        val transposedMatrix =  (0 until 4).map { outerCounter ->
 | 
				
			||||||
            Array<UByte>(4) { 0U }
 | 
					            UByteArray(4) { 0U }
 | 
				
			||||||
        }.toTypedArray()
 | 
					        }
 | 
				
			||||||
        for (i in 0 until 4) {
 | 
					        for (i in 0 until 4) {
 | 
				
			||||||
            for (j in 0 until 4) {
 | 
					            for (j in 0 until 4) {
 | 
				
			||||||
                transposedMatrix[i][j] = state[j][i]
 | 
					                transposedMatrix[i][j] = state[j][i]
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        printState(transposedMatrix)
 | 
					 | 
				
			||||||
        state.forEach { clearArray(it) }
 | 
					        state.forEach { clearArray(it) }
 | 
				
			||||||
        completed = true
 | 
					        completed = true
 | 
				
			||||||
        return transposedMatrix.flatten().toTypedArray()
 | 
					        return transposedMatrix.flattenToUByteArray()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun clearArray(array : Array<UByte>) {
 | 
					    private fun clearArray(array : UByteArray) {
 | 
				
			||||||
        array.indices.forEach { array[it] = 0U }
 | 
					        array.indices.forEach { array[it] = 0U }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -342,7 +343,7 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun printState(specific : Array<Array<UByte>>) {
 | 
					    private fun printState(specific : List<UByteArray>) {
 | 
				
			||||||
        if (!debug) {
 | 
					        if (!debug) {
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -356,7 +357,7 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sealed class AesKey(val key: String, val keyLength: Int) {
 | 
					sealed class AesKey(val key: String, val keyLength: Int) {
 | 
				
			||||||
    val keyArray: Array<UByte> = key.chunked(2).map { it.toUByte(16) }.toTypedArray()
 | 
					    val keyArray: UByteArray = key.chunked(2).map { it.toUByte(16) }.toUByteArray()
 | 
				
			||||||
    val numberOf32BitWords = keyLength / 32
 | 
					    val numberOf32BitWords = keyLength / 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Aes128Key(key: String) : AesKey(key, 128)
 | 
					    class Aes128Key(key: String) : AesKey(key, 128)
 | 
				
			||||||
@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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.symmetric
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 18-Sep-2019
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class Mode {
 | 
				
			||||||
 | 
					    ENCRYPT, DECRYPT
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,262 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					fun Array<Byte>.hexColumsPrint() {
 | 
				
			||||||
 | 
					    val printout = this.map { it.toString(16) }.chunked(16)
 | 
				
			||||||
 | 
					    printout.forEach { println(it.joinToString(separator = " ") { it.toUpperCase() }) }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun Array<UByte>.hexColumsPrint(chunk : Int = 16) {
 | 
				
			||||||
 | 
					    val printout = this.map { it.toString(16).padStart(2, '0') }.chunked(chunk)
 | 
				
			||||||
 | 
					    printout.forEach { println(it.joinToString(separator = " ") { it.toUpperCase() }) }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun UByteArray.hexColumsPrint(chunk : Int = 16) {
 | 
				
			||||||
 | 
					    val printout = this.map { it.toString(16).padStart(2, '0') }.chunked(chunk)
 | 
				
			||||||
 | 
					    printout.forEach { println(it.joinToString(separator = " ") { it.toUpperCase() }) }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun Array<ULong>.hexColumsPrint(chunk: Int = 3) {
 | 
				
			||||||
 | 
					    val printout = this.map { it.toString(16) }.chunked(chunk)
 | 
				
			||||||
 | 
					    printout.forEach { println(it.joinToString(separator = " ") { it.toUpperCase() }) }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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] }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun String.hexStringToTypedUByteArray() : Array<UByte> {
 | 
				
			||||||
 | 
					    return this.chunked(2).map { it.toUByte(16) }.toTypedArray()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun String.hexStringToUByteArray() : UByteArray {
 | 
				
			||||||
 | 
					    return this.chunked(2).map { it.toUByte(16) }.toUByteArray()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun Array<UByte>.toHexString() : String {
 | 
				
			||||||
 | 
					    return this.joinToString(separator = "") {
 | 
				
			||||||
 | 
					        if (it <= 0x0FU) {
 | 
				
			||||||
 | 
					            "0${it.toString(16)}"
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            it.toString(16)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun UByteArray.toHexString() : String {
 | 
				
			||||||
 | 
					    return this.joinToString(separator = "") {
 | 
				
			||||||
 | 
					        if (it <= 0x0FU) {
 | 
				
			||||||
 | 
					            "0${it.toString(16)}"
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            it.toString(16)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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 {
 | 
				
			||||||
 | 
					        Crypto.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) }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto.hash.blake2b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.Crypto
 | 
				
			||||||
 | 
					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 = Crypto.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 = Crypto.Blake2b.updateable()
 | 
				
			||||||
 | 
					        blake2b.update("t".encodeToUByteArray())
 | 
				
			||||||
 | 
					        blake2b.update(("est".encodeToUByteArray()))
 | 
				
			||||||
 | 
					        val result = blake2b.digest().toHexString()
 | 
				
			||||||
 | 
					//        println("Result: $result")
 | 
				
			||||||
 | 
					        assertTrue { result == expected }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto.hash.sha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.Crypto
 | 
				
			||||||
 | 
					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() {
 | 
				
			||||||
 | 
					        val expected = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
 | 
				
			||||||
 | 
					        val result = Crypto.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() {
 | 
				
			||||||
 | 
					        val expected = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
 | 
				
			||||||
 | 
					        val sha256 = Crypto.Sha256.updateable()
 | 
				
			||||||
 | 
					        sha256.update("t".encodeToUByteArray())
 | 
				
			||||||
 | 
					        sha256.update(("est".encodeToUByteArray()))
 | 
				
			||||||
 | 
					        val result = sha256.digest().toHexString()
 | 
				
			||||||
 | 
					//        println("Result: $result")
 | 
				
			||||||
 | 
					        assertTrue { result == expected }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto.hash.sha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.Crypto
 | 
				
			||||||
 | 
					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() {
 | 
				
			||||||
 | 
					        val expected = "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67" +
 | 
				
			||||||
 | 
					                "b143732c304cc5fa9ad8e6f57f50028a8ff"
 | 
				
			||||||
 | 
					        val result = Crypto.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() {
 | 
				
			||||||
 | 
					        val expected = "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67" +
 | 
				
			||||||
 | 
					                "b143732c304cc5fa9ad8e6f57f50028a8ff"
 | 
				
			||||||
 | 
					        val sha512 = Crypto.Sha512.updateable()
 | 
				
			||||||
 | 
					        sha512.update("t".encodeToUByteArray())
 | 
				
			||||||
 | 
					        sha512.update(("est".encodeToUByteArray()))
 | 
				
			||||||
 | 
					        val result = sha512.digest().toHexString()
 | 
				
			||||||
 | 
					//        println("Result: $result")
 | 
				
			||||||
 | 
					        assertTrue { result == expected }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 20-Jul-2019
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					expect fun testBlocking(block : suspend () -> Unit)
 | 
				
			||||||
@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					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()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto.hash.blake2b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.getSodium
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.hash.sha.Sha256StatelessDelegated
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.util.toHexString
 | 
				
			||||||
 | 
					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) : Blake2b {
 | 
				
			||||||
 | 
					    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 : Blake2bStateless {
 | 
				
			||||||
 | 
					    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
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto.hash.sha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.getSodium
 | 
				
			||||||
 | 
					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 : Sha512 {
 | 
				
			||||||
 | 
					    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 : StatelessSha512 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					@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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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() }
 | 
				
			||||||
@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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.toUByteArray()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					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) : Blake2b {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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.toUByteArray()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual object Blake2bDelegatedStateless : Blake2bStateless {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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.toUByteArray()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					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.toUByteArray()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.toUByteArray()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					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 : Sha512 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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.toUByteArray()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual object Sha512StatelessDelegated : StatelessSha512 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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.toUByteArray()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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() }
 | 
				
			||||||
@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto.hash.sha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 07-Jun-2020
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					import platform.posix.*
 | 
				
			||||||
 | 
					//import cin
 | 
				
			||||||
@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					//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() }
 | 
				
			||||||
 | 
					//        }
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					//}
 | 
				
			||||||
@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					headers = sodium.h
 | 
				
			||||||
 | 
					headerFilter = sodium.h sodium/**
 | 
				
			||||||
 | 
					#staticLibraries = libsodium.a
 | 
				
			||||||
 | 
					#libraryPaths = sodiumWrapper/lib
 | 
				
			||||||
 | 
					#compilerOpts = -I./sodiumWrapper/include
 | 
				
			||||||
 | 
					linkerOpts =
 | 
				
			||||||
@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import kotlinx.atomicfu.AtomicBoolean
 | 
				
			||||||
 | 
					import kotlinx.coroutines.Dispatchers
 | 
				
			||||||
 | 
					import kotlinx.coroutines.GlobalScope
 | 
				
			||||||
 | 
					import kotlinx.coroutines.launch
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto.hash.blake2b
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.util.toHexString
 | 
				
			||||||
 | 
					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) : Blake2b {
 | 
				
			||||||
 | 
					    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.toUByteArray().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.addressOf(0), requestedHashLength.convert())
 | 
				
			||||||
 | 
					        free(state.ptr)
 | 
				
			||||||
 | 
					        return hashResult
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
 | 
				
			||||||
 | 
					actual object Blake2bDelegatedStateless : Blake2bStateless {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun digest(inputMessage: UByteArray, key: UByteArray, hashLength: Int): UByteArray {
 | 
				
			||||||
 | 
					        val hashResult = UByteArray(MAX_HASH_BYTES)
 | 
				
			||||||
 | 
					        val hashResultPinned = hashResult.pin()
 | 
				
			||||||
 | 
					        crypto_generichash(
 | 
				
			||||||
 | 
					            hashResultPinned.addressOf(0),
 | 
				
			||||||
 | 
					            hashLength.convert(),
 | 
				
			||||||
 | 
					            inputMessage.toCValues(),
 | 
				
			||||||
 | 
					            inputMessage.size.convert(),
 | 
				
			||||||
 | 
					            key.toCValues(),
 | 
				
			||||||
 | 
					            key.size.convert()
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        hashResultPinned.unpin()
 | 
				
			||||||
 | 
					        return hashResult
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto.hash.sha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bDelegatedStateless
 | 
				
			||||||
 | 
					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 = 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.addressOf(0))
 | 
				
			||||||
 | 
					        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.addressOf(0), inputMessage.toCValues(), inputMessage.size.convert())
 | 
				
			||||||
 | 
					        hashResultPinned.unpin()
 | 
				
			||||||
 | 
					        return hashResult
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto.hash.sha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 : Sha512 {
 | 
				
			||||||
 | 
					    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.addressOf(0))
 | 
				
			||||||
 | 
					        free(state.ptr)
 | 
				
			||||||
 | 
					        return hashResult
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual object Sha512StatelessDelegated : StatelessSha512 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun digest(inputMessage: UByteArray): UByteArray {
 | 
				
			||||||
 | 
					        val hashResult = UByteArray(Sha512StatelessDelegated.MAX_HASH_BYTES)
 | 
				
			||||||
 | 
					        val hashResultPinned = hashResult.pin()
 | 
				
			||||||
 | 
					        crypto_hash_sha512(hashResultPinned.addressOf(0), inputMessage.toCValues(), inputMessage.size.convert())
 | 
				
			||||||
 | 
					        hashResultPinned.unpin()
 | 
				
			||||||
 | 
					        return hashResult
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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() }
 | 
				
			||||||
@ -16,12 +16,8 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@file:Suppress("UnstableApiUsage")
 | 
					@file:Suppress("UnstableApiUsage")
 | 
				
			||||||
 | 
					 | 
				
			||||||
import com.moowork.gradle.node.task.NodeTask
 | 
					 | 
				
			||||||
import org.gradle.api.tasks.testing.logging.TestLogging
 | 
					 | 
				
			||||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest
 | 
					import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest
 | 
				
			||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
 | 
					import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
 | 
				
			||||||
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
plugins {
 | 
					plugins {
 | 
				
			||||||
    kotlin(PluginsDeps.multiplatform)
 | 
					    kotlin(PluginsDeps.multiplatform)
 | 
				
			||||||
@ -46,53 +42,29 @@ repositories {
 | 
				
			|||||||
    jcenter()
 | 
					    jcenter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
group = "com.ionspin.kotlin"
 | 
					group = ReleaseInfo.group
 | 
				
			||||||
version = "0.0.4-SNAPSHOT"
 | 
					version = ReleaseInfo.version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
val ideaActive = System.getProperty("idea.active") == "true"
 | 
					val ideaActive = System.getProperty("idea.active") == "true"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fun getHostOsName(): String {
 | 
					 | 
				
			||||||
    val target = System.getProperty("os.name")
 | 
					 | 
				
			||||||
    if (target == "Linux") return "linux"
 | 
					 | 
				
			||||||
    if (target.startsWith("Windows")) return "windows"
 | 
					 | 
				
			||||||
    if (target.startsWith("Mac")) return "macos"
 | 
					 | 
				
			||||||
    return "unknown"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
kotlin {
 | 
					kotlin {
 | 
				
			||||||
    val hostOsName = getHostOsName()
 | 
					    val hostOsName = getHostOsName()
 | 
				
			||||||
    if (ideaActive) {
 | 
					    runningOnLinuxx86_64 {
 | 
				
			||||||
        when(hostOsName) {
 | 
					 | 
				
			||||||
            "linux" -> linuxX64("native")
 | 
					 | 
				
			||||||
            "macos" -> macosX64("native")
 | 
					 | 
				
			||||||
            "windows" -> mingwX64("native")
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (hostOsName == "linux") {
 | 
					 | 
				
			||||||
        jvm()
 | 
					        jvm()
 | 
				
			||||||
        js {
 | 
					        js {
 | 
				
			||||||
            compilations {
 | 
					 | 
				
			||||||
                this.forEach {
 | 
					 | 
				
			||||||
                    it.compileKotlinTask.kotlinOptions.sourceMap = true
 | 
					 | 
				
			||||||
                    it.compileKotlinTask.kotlinOptions.moduleKind = "commonjs"
 | 
					 | 
				
			||||||
                    it.compileKotlinTask.kotlinOptions.metaInfo = true
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (it.name == "main") {
 | 
					        browser {
 | 
				
			||||||
                        it.compileKotlinTask.kotlinOptions.main = "call"
 | 
					
 | 
				
			||||||
                    }
 | 
					            testTask {
 | 
				
			||||||
                    println("Compilation name ${it.name} set")
 | 
					//                isRunningInTravis {
 | 
				
			||||||
                    println("Destination dir ${it.compileKotlinTask.destinationDir}")
 | 
					                    enabled = false //Until I sort out testing on travis, and figure out how to increase karma timeout
 | 
				
			||||||
 | 
					//                }
 | 
				
			||||||
 | 
					                useKarma {
 | 
				
			||||||
 | 
					                    useChrome()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
            //Until I figure out how to run headless chrome on travis
 | 
					 | 
				
			||||||
//        browser {
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//            testTask {
 | 
					 | 
				
			||||||
//                useKarma {
 | 
					 | 
				
			||||||
//                    useChrome()
 | 
					 | 
				
			||||||
//                }
 | 
					 | 
				
			||||||
//            }
 | 
					 | 
				
			||||||
//        }
 | 
					 | 
				
			||||||
            nodejs {
 | 
					            nodejs {
 | 
				
			||||||
                testTask {
 | 
					                testTask {
 | 
				
			||||||
                    useMocha() {
 | 
					                    useMocha() {
 | 
				
			||||||
@ -105,39 +77,41 @@ kotlin {
 | 
				
			|||||||
        linuxX64("linux") {
 | 
					        linuxX64("linux") {
 | 
				
			||||||
            binaries {
 | 
					            binaries {
 | 
				
			||||||
                staticLib {
 | 
					                staticLib {
 | 
				
			||||||
 | 
					                    optimized = true
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        linuxArm64() {
 | 
				
			||||||
 | 
					            binaries {
 | 
				
			||||||
 | 
					                staticLib {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        //Not supported in coroutines at the moment
 | 
					
 | 
				
			||||||
//        linuxArm32Hfp() {
 | 
					        linuxArm32Hfp() {
 | 
				
			||||||
//            binaries {
 | 
					            binaries {
 | 
				
			||||||
//                staticLib {
 | 
					                staticLib {
 | 
				
			||||||
//                }
 | 
					                }
 | 
				
			||||||
//            }
 | 
					            }
 | 
				
			||||||
//        }
 | 
					        }
 | 
				
			||||||
        //Not supported in coroutines at the moment
 | 
					
 | 
				
			||||||
//        linuxArm64() {
 | 
					
 | 
				
			||||||
//            binaries {
 | 
					 | 
				
			||||||
//                staticLib {
 | 
					 | 
				
			||||||
//                }
 | 
					 | 
				
			||||||
//            }
 | 
					 | 
				
			||||||
//        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (hostOsName == "macos") {
 | 
					    runningOnMacos {
 | 
				
			||||||
        iosX64("ios") {
 | 
					        iosX64("ios") {
 | 
				
			||||||
            binaries {
 | 
					            binaries {
 | 
				
			||||||
                framework {
 | 
					                framework {
 | 
				
			||||||
 | 
					                    optimized = true
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        iosArm64("ios64Arm") {
 | 
					        iosArm64("ios64Arm") {
 | 
				
			||||||
            binaries {
 | 
					            binaries {
 | 
				
			||||||
                framework {
 | 
					                framework {
 | 
				
			||||||
 | 
					                    optimized = true
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -145,24 +119,24 @@ kotlin {
 | 
				
			|||||||
        iosArm32("ios32Arm") {
 | 
					        iosArm32("ios32Arm") {
 | 
				
			||||||
            binaries {
 | 
					            binaries {
 | 
				
			||||||
                framework {
 | 
					                framework {
 | 
				
			||||||
 | 
					                    optimized = true
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        macosX64() {
 | 
					        macosX64() {
 | 
				
			||||||
            binaries {
 | 
					            binaries {
 | 
				
			||||||
                framework {
 | 
					                framework {
 | 
				
			||||||
 | 
					                    optimized = true
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (hostOsName == "windows") {
 | 
					    runningOnWindows {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        mingwX64() {
 | 
					        mingwX64() {
 | 
				
			||||||
            binaries {
 | 
					            binaries {
 | 
				
			||||||
                staticLib {
 | 
					                staticLib {
 | 
				
			||||||
 | 
					                    optimized = true
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -186,6 +160,7 @@ kotlin {
 | 
				
			|||||||
                implementation(kotlin(Deps.Common.test))
 | 
					                implementation(kotlin(Deps.Common.test))
 | 
				
			||||||
                implementation(Deps.Common.coroutines)
 | 
					                implementation(Deps.Common.coroutines)
 | 
				
			||||||
                implementation(Deps.Common.kotlinBigNum)
 | 
					                implementation(Deps.Common.kotlinBigNum)
 | 
				
			||||||
 | 
					                implementation(project(Deps.Common.apiProject))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        val commonTest by getting {
 | 
					        val commonTest by getting {
 | 
				
			||||||
@ -195,42 +170,49 @@ kotlin {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val nativeMain = if (ideaActive) {
 | 
					
 | 
				
			||||||
            val nativeMain by getting {
 | 
					 | 
				
			||||||
                dependsOn(commonMain)
 | 
					 | 
				
			||||||
                dependencies {
 | 
					 | 
				
			||||||
                    implementation(Deps.Native.coroutines)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            nativeMain
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
        val nativeMain by creating {
 | 
					        val nativeMain by creating {
 | 
				
			||||||
            dependsOn(commonMain)
 | 
					            dependsOn(commonMain)
 | 
				
			||||||
            dependencies {
 | 
					            dependencies {
 | 
				
			||||||
                implementation(Deps.Native.coroutines)
 | 
					                implementation(Deps.Native.coroutines)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            }
 | 
					            isRunningInIdea {
 | 
				
			||||||
            nativeMain
 | 
					                kotlin.setSrcDirs(emptySet<String>())
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        val nativeTest = if (ideaActive) {
 | 
					 | 
				
			||||||
            val nativeTest by getting {
 | 
					 | 
				
			||||||
                dependsOn(commonTest)
 | 
					 | 
				
			||||||
                dependencies {
 | 
					 | 
				
			||||||
                    implementation(Deps.Native.coroutines)
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
            nativeTest
 | 
					
 | 
				
			||||||
        } else {
 | 
					
 | 
				
			||||||
        val nativeTest by creating {
 | 
					        val nativeTest by creating {
 | 
				
			||||||
            dependsOn(commonTest)
 | 
					            dependsOn(commonTest)
 | 
				
			||||||
            dependencies {
 | 
					            dependencies {
 | 
				
			||||||
                implementation(Deps.Native.coroutines)
 | 
					                implementation(Deps.Native.coroutines)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
            nativeTest
 | 
					
 | 
				
			||||||
 | 
					        targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
 | 
				
			||||||
 | 
					            compilations.getByName("main") {
 | 
				
			||||||
 | 
					                println("Setting native sourceset dependancy for $name")
 | 
				
			||||||
 | 
					                if ((this@withType.name.contains("ios") ||
 | 
				
			||||||
 | 
					                            this@withType.name.contains("mingw")).not()
 | 
				
			||||||
 | 
					                ) {
 | 
				
			||||||
 | 
					                    println("Setting native sourceset dependancy for $this@withType.name")
 | 
				
			||||||
 | 
					                    defaultSourceSet.dependsOn(nativeMain)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            compilations.getByName("test") {
 | 
				
			||||||
 | 
					                println("Setting native sourceset dependancy for $name")
 | 
				
			||||||
 | 
					                if ((this@withType.name.contains("ios") ||
 | 
				
			||||||
 | 
					                            this@withType.name.contains("mingw")).not()
 | 
				
			||||||
 | 
					                ) {
 | 
				
			||||||
 | 
					                    println("Setting native sourceset dependancy for $this@withType.name")
 | 
				
			||||||
 | 
					                    defaultSourceSet.dependsOn(nativeTest)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (hostOsName == "linux") {
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        runningOnLinuxx86_64 {
 | 
				
			||||||
            val jvmMain by getting {
 | 
					            val jvmMain by getting {
 | 
				
			||||||
                dependencies {
 | 
					                dependencies {
 | 
				
			||||||
                    implementation(kotlin(Deps.Jvm.stdLib))
 | 
					                    implementation(kotlin(Deps.Jvm.stdLib))
 | 
				
			||||||
@ -250,41 +232,50 @@ kotlin {
 | 
				
			|||||||
            val jsMain by getting {
 | 
					            val jsMain by getting {
 | 
				
			||||||
                dependencies {
 | 
					                dependencies {
 | 
				
			||||||
                    implementation(kotlin(Deps.Js.stdLib))
 | 
					                    implementation(kotlin(Deps.Js.stdLib))
 | 
				
			||||||
                    implementation(kotlin(Deps.Js.test))
 | 
					 | 
				
			||||||
                    implementation(Deps.Js.coroutines)
 | 
					                    implementation(Deps.Js.coroutines)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            val jsTest by getting {
 | 
					            val jsTest by getting {
 | 
				
			||||||
                dependencies {
 | 
					                dependencies {
 | 
				
			||||||
                    implementation(kotlin("test-js"))
 | 
					                    implementation(Deps.Js.coroutines)
 | 
				
			||||||
 | 
					                    implementation(kotlin(Deps.Js.test))
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            val linuxMain by getting {
 | 
					            val linuxMain by getting {
 | 
				
			||||||
                dependsOn(nativeMain)
 | 
					                dependsOn(nativeMain)
 | 
				
			||||||
 | 
					                //Force idea to consider native sourceset
 | 
				
			||||||
 | 
					                if (ideaActive) {
 | 
				
			||||||
 | 
					                    kotlin.srcDir("src/nativeMain/kotlin")
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            val linuxTest by getting {
 | 
					            val linuxTest by getting {
 | 
				
			||||||
                dependsOn(nativeTest)
 | 
					                dependsOn(nativeTest)
 | 
				
			||||||
 | 
					//                Force idea to consider native sourceset
 | 
				
			||||||
 | 
					                if (ideaActive) {
 | 
				
			||||||
 | 
					                    kotlin.srcDir("src/nativeTest/kotlin")
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            //Not supported in coroutines at the moment
 | 
					 | 
				
			||||||
//            val linuxArm32HfpMain by getting {
 | 
					 | 
				
			||||||
//                dependsOn(nativeMain)
 | 
					 | 
				
			||||||
//            }
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//            val linuxArm32HfpTest by getting {
 | 
					 | 
				
			||||||
//                dependsOn(nativeTest)
 | 
					 | 
				
			||||||
//            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
//            val linuxArm64Main by getting {
 | 
					            val linuxArm64Main by getting {
 | 
				
			||||||
//                dependsOn(nativeMain)
 | 
					                dependsOn(nativeMain)
 | 
				
			||||||
//            }
 | 
					            }
 | 
				
			||||||
//
 | 
					
 | 
				
			||||||
//            val linuxArm64Test by getting {
 | 
					            val linuxArm64Test by getting {
 | 
				
			||||||
//                dependsOn(nativeTest)
 | 
					                dependsOn(nativeTest)
 | 
				
			||||||
//            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            val linuxArm32HfpMain by getting {
 | 
				
			||||||
 | 
					                dependsOn(nativeMain)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            val linuxArm32HfpTest by getting {
 | 
				
			||||||
 | 
					                dependsOn(nativeTest)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (hostOsName == "macos") {
 | 
					
 | 
				
			||||||
 | 
					        runningOnMacos{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            val iosMain by getting {
 | 
					            val iosMain by getting {
 | 
				
			||||||
                dependsOn(nativeMain)
 | 
					                dependsOn(nativeMain)
 | 
				
			||||||
@ -308,10 +299,16 @@ kotlin {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            val macosX64Main by getting {
 | 
					            val macosX64Main by getting {
 | 
				
			||||||
                dependsOn(nativeMain)
 | 
					                dependsOn(commonMain)
 | 
				
			||||||
 | 
					                if (ideaActive) {
 | 
				
			||||||
 | 
					                    kotlin.srcDir("src/nativeMain/kotlin")
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            val macosX64Test by getting {
 | 
					            val macosX64Test by getting {
 | 
				
			||||||
                dependsOn(nativeTest)
 | 
					                dependsOn(commonTest)
 | 
				
			||||||
 | 
					                if (ideaActive) {
 | 
				
			||||||
 | 
					                    kotlin.srcDir("src/nativeTest/kotlin")
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -327,7 +324,7 @@ kotlin {
 | 
				
			|||||||
//            dependsOn(commonTest)
 | 
					//            dependsOn(commonTest)
 | 
				
			||||||
//        }
 | 
					//        }
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
        if (hostOsName == "windows") {
 | 
					        runningOnWindows {
 | 
				
			||||||
            val mingwX64Main by getting {
 | 
					            val mingwX64Main by getting {
 | 
				
			||||||
                dependsOn(commonMain)
 | 
					                dependsOn(commonMain)
 | 
				
			||||||
                dependencies {
 | 
					                dependencies {
 | 
				
			||||||
@ -343,6 +340,8 @@ kotlin {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        all {
 | 
					        all {
 | 
				
			||||||
            languageSettings.enableLanguageFeature("InlineClasses")
 | 
					            languageSettings.enableLanguageFeature("InlineClasses")
 | 
				
			||||||
 | 
					            languageSettings.useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
 | 
				
			||||||
 | 
					            languageSettings.useExperimentalAnnotation("kotlin.ExperimentalStdlibApi")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -376,15 +375,12 @@ tasks {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        sourceRoot {
 | 
					        sourceRoot {
 | 
				
			||||||
            println("Common !")
 | 
					            println("Common !")
 | 
				
			||||||
            path = "/home/ionspin/Projects/Future/kotlin-multiplatform-crypto/crypto/src/commonMain" //TODO remove static path!
 | 
					            path =
 | 
				
			||||||
 | 
					                "/home/ionspin/Projects/Future/kotlin-multiplatform-crypto/crypto/src/commonMain" //TODO remove static path!
 | 
				
			||||||
            platforms = listOf("Common")
 | 
					            platforms = listOf("Common")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (getHostOsName() == "linux") {
 | 
					    if (getHostOsName() == "linux" && getHostArchitecture() == "x86-64") {
 | 
				
			||||||
 | 
					 | 
				
			||||||
        val npmInstall by getting
 | 
					 | 
				
			||||||
        val compileKotlinJs by getting(AbstractCompile::class)
 | 
					 | 
				
			||||||
        val compileTestKotlinJs by getting(Kotlin2JsCompile::class)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val jvmTest by getting(Test::class) {
 | 
					        val jvmTest by getting(Test::class) {
 | 
				
			||||||
            testLogging {
 | 
					            testLogging {
 | 
				
			||||||
@ -400,21 +396,20 @@ tasks {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val jsIrNodeTest by getting(KotlinJsTest::class) {
 | 
					        val jsNodeTest by getting(KotlinJsTest::class) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
            testLogging {
 | 
					            testLogging {
 | 
				
			||||||
                events("PASSED", "FAILED", "SKIPPED")
 | 
					                events("PASSED", "FAILED", "SKIPPED")
 | 
				
			||||||
                showStandardStreams = true
 | 
					                showStandardStreams = true
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val legacyjsNodeTest by getting(KotlinJsTest::class) {
 | 
					//        val legacyjsNodeTest by getting(KotlinJsTest::class) {
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
            testLogging {
 | 
					//            testLogging {
 | 
				
			||||||
                events("PASSED", "FAILED", "SKIPPED")
 | 
					//                events("PASSED", "FAILED", "SKIPPED")
 | 
				
			||||||
                showStandardStreams = true
 | 
					//                showStandardStreams = true
 | 
				
			||||||
            }
 | 
					//            }
 | 
				
			||||||
        }
 | 
					//        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//        val jsIrBrowserTest by getting(KotlinJsTest::class) {
 | 
					//        val jsIrBrowserTest by getting(KotlinJsTest::class) {
 | 
				
			||||||
//            testLogging {
 | 
					//            testLogging {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,21 +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.
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
distributionBase=GRADLE_USER_HOME
 | 
					 | 
				
			||||||
distributionPath=wrapper/dists
 | 
					 | 
				
			||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip
 | 
					 | 
				
			||||||
zipStoreBase=GRADLE_USER_HOME
 | 
					 | 
				
			||||||
zipStorePath=wrapper/dists
 | 
					 | 
				
			||||||
@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					package com.ionspin.kotlin.crypto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bProperties
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bPure
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.hash.sha.Sha256Pure
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.hash.sha.Sha512Pure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 24-May-2020
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typealias Blake2bPureStateless = Blake2bPure.Companion
 | 
				
			||||||
 | 
					typealias Sha256PureStateless = Sha256Pure.Companion
 | 
				
			||||||
 | 
					typealias Sha512PureStateless = Sha512Pure.Companion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					object Crypto : CryptoProvider {
 | 
				
			||||||
 | 
					    override suspend fun initialize() {
 | 
				
			||||||
 | 
					        //Nothing to do atm.
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun initializeWithCallback(done: () -> Unit) {
 | 
				
			||||||
 | 
					        done()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    object Blake2b {
 | 
				
			||||||
 | 
					        fun updateable(key: UByteArray? = null, hashLength: Int = Blake2bProperties.MAX_HASH_BYTES): com.ionspin.kotlin.crypto.hash.blake2b.Blake2b {
 | 
				
			||||||
 | 
					            checkInitialization()
 | 
				
			||||||
 | 
					            return Blake2bPure(key, hashLength)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fun stateless(message: UByteArray, key: UByteArray = ubyteArrayOf(), hashLength: Int = Blake2bProperties.MAX_HASH_BYTES): UByteArray {
 | 
				
			||||||
 | 
					            checkInitialization()
 | 
				
			||||||
 | 
					            return Blake2bPureStateless.digest(message, key, hashLength)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    object Sha256 {
 | 
				
			||||||
 | 
					        fun updateable(): com.ionspin.kotlin.crypto.hash.sha.Sha256 {
 | 
				
			||||||
 | 
					            checkInitialization()
 | 
				
			||||||
 | 
					            return Sha256Pure()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fun stateless(message: UByteArray) : UByteArray{
 | 
				
			||||||
 | 
					            checkInitialization()
 | 
				
			||||||
 | 
					            return Sha256PureStateless.digest(inputMessage =  message)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    object Sha512 {
 | 
				
			||||||
 | 
					        fun updateable(): com.ionspin.kotlin.crypto.hash.sha.Sha512 {
 | 
				
			||||||
 | 
					            checkInitialization()
 | 
				
			||||||
 | 
					            return Sha512Pure()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fun stateless(message: UByteArray) : UByteArray {
 | 
				
			||||||
 | 
					            checkInitialization()
 | 
				
			||||||
 | 
					            return Sha512PureStateless.digest(inputMessage =  message)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun checkInitialization() {
 | 
				
			||||||
 | 
					        // Nothing to do atm
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					package _multiplatform_crypto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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
 | 
				
			||||||
@ -22,5 +22,5 @@ package com.ionspin.kotlin.crypto
 | 
				
			|||||||
 * on 21-Sep-2019
 | 
					 * on 21-Sep-2019
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
expect object SRNG {
 | 
					expect object SRNG {
 | 
				
			||||||
    fun getRandomBytes(amount : Int) : Array<UByte>
 | 
					    fun getRandomBytes(amount : Int) : UByteArray
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -19,9 +19,6 @@ package com.ionspin.kotlin.crypto.hash.blake2b
 | 
				
			|||||||
import com.ionspin.kotlin.bignum.integer.BigInteger
 | 
					import com.ionspin.kotlin.bignum.integer.BigInteger
 | 
				
			||||||
import com.ionspin.kotlin.bignum.integer.toBigInteger
 | 
					import com.ionspin.kotlin.bignum.integer.toBigInteger
 | 
				
			||||||
import com.ionspin.kotlin.crypto.*
 | 
					import com.ionspin.kotlin.crypto.*
 | 
				
			||||||
import com.ionspin.kotlin.crypto.hash.StatelessHash
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.hash.UpdatableHash
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.chunked
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.rotateRight
 | 
					import com.ionspin.kotlin.crypto.util.rotateRight
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -30,11 +27,15 @@ import com.ionspin.kotlin.crypto.util.rotateRight
 | 
				
			|||||||
 * on 14-Jul-2019
 | 
					 * on 14-Jul-2019
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ExperimentalUnsignedTypes
 | 
					 | 
				
			||||||
class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : UpdatableHash {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    companion object : StatelessHash {
 | 
					class Blake2bPure(val key: UByteArray? = null, val hashLength: Int = 64) : Blake2b {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    companion object : Blake2bStateless {
 | 
				
			||||||
 | 
					        //Hack start
 | 
				
			||||||
 | 
					        //If this line is not included konanc 1.4-M1 fails to link because it cant find ByteArray which is
 | 
				
			||||||
 | 
					        //a backing class for UByteArray
 | 
				
			||||||
 | 
					        val byteArray: ByteArray = byteArrayOf(0, 1)
 | 
				
			||||||
 | 
					        //Hack end
 | 
				
			||||||
        const val BITS_IN_WORD = 64
 | 
					        const val BITS_IN_WORD = 64
 | 
				
			||||||
        const val ROUNDS_IN_COMPRESS = 12
 | 
					        const val ROUNDS_IN_COMPRESS = 12
 | 
				
			||||||
        const val BLOCK_BYTES = 128
 | 
					        const val BLOCK_BYTES = 128
 | 
				
			||||||
@ -103,7 +104,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        fun compress(
 | 
					        fun compress(
 | 
				
			||||||
            h: Array<ULong>,
 | 
					            h: Array<ULong>,
 | 
				
			||||||
            input: Array<UByte>,
 | 
					            input: UByteArray,
 | 
				
			||||||
            offsetCounter: BigInteger,
 | 
					            offsetCounter: BigInteger,
 | 
				
			||||||
            finalBlock: Boolean
 | 
					            finalBlock: Boolean
 | 
				
			||||||
        ): Array<ULong> {
 | 
					        ): Array<ULong> {
 | 
				
			||||||
@ -130,7 +131,6 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
            v[13] = v[13] xor (offsetCounter shr BITS_IN_WORD).ulongValue()
 | 
					            v[13] = v[13] xor (offsetCounter shr BITS_IN_WORD).ulongValue()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (finalBlock) {
 | 
					            if (finalBlock) {
 | 
				
			||||||
//            v[14] = v[14] xor 0xFFFFFFFFFFFFFFFFUL
 | 
					 | 
				
			||||||
                v[14] = v[14].inv()
 | 
					                v[14] = v[14].inv()
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -144,25 +144,25 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
            return h
 | 
					            return h
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @ExperimentalStdlibApi
 | 
					
 | 
				
			||||||
        override fun digest(inputString: String, key: String?, hashLength: Int): Array<UByte> {
 | 
					        fun digest(inputString: String, key: String?, hashLength: Int): UByteArray {
 | 
				
			||||||
            val array = inputString.encodeToByteArray().map { it.toUByte() }.toList().toTypedArray()
 | 
					            val array = inputString.encodeToByteArray().toUByteArray()
 | 
				
			||||||
            val keyBytes = key?.run {
 | 
					            val keyBytes = key?.run {
 | 
				
			||||||
                encodeToByteArray().map { it.toUByte() }.toTypedArray()
 | 
					                encodeToByteArray().toUByteArray()
 | 
				
			||||||
            } ?: emptyArray()
 | 
					            } ?: ubyteArrayOf()
 | 
				
			||||||
            return digest(inputMessage = array, key = keyBytes, hashLength = hashLength)
 | 
					            return digest(inputMessage = array, key = keyBytes, hashLength = hashLength)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        override fun digest(
 | 
					        override fun digest(
 | 
				
			||||||
            inputMessage: Array<UByte>,
 | 
					            inputMessage: UByteArray,
 | 
				
			||||||
            key: Array<UByte>,
 | 
					            key: UByteArray,
 | 
				
			||||||
            hashLength: Int
 | 
					            hashLength: Int
 | 
				
			||||||
        ): Array<UByte> {
 | 
					        ): UByteArray {
 | 
				
			||||||
            if (hashLength > MAX_HASH_BYTES) {
 | 
					            if (hashLength > MAX_HASH_BYTES) {
 | 
				
			||||||
                throw RuntimeException("Invalid hash length. Requested length more than maximum length. Requested length $hashLength")
 | 
					                throw RuntimeException("Invalid hash length. Requested length more than maximum length. Requested length $hashLength")
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            val chunkedMessage = inputMessage.chunked(BLOCK_BYTES)
 | 
					            val chunkedMessage = inputMessage.chunked(BLOCK_BYTES).map { it.toUByteArray() }.toTypedArray()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            val h = iv.copyOf()
 | 
					            val h = iv.copyOf()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -172,7 +172,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
            val message = if (key.isEmpty()) {
 | 
					            val message = if (key.isEmpty()) {
 | 
				
			||||||
                if (chunkedMessage.isEmpty()) {
 | 
					                if (chunkedMessage.isEmpty()) {
 | 
				
			||||||
                    Array(1) {
 | 
					                    Array(1) {
 | 
				
			||||||
                        Array<UByte>(128) {
 | 
					                        UByteArray(128) {
 | 
				
			||||||
                            0U
 | 
					                            0U
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -199,7 +199,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
            val lastBlockPadded = if (message.isNotEmpty()) {
 | 
					            val lastBlockPadded = if (message.isNotEmpty()) {
 | 
				
			||||||
                padToBlock(message[message.size - 1])
 | 
					                padToBlock(message[message.size - 1])
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                Array<UByte>(16) { 0U }
 | 
					                UByteArray(16) { 0U }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            compress(h, lastBlockPadded, lastSize.toBigInteger(), true).copyInto(h)
 | 
					            compress(h, lastBlockPadded, lastSize.toBigInteger(), true).copyInto(h)
 | 
				
			||||||
@ -208,7 +208,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
            return formatResult(h).copyOfRange(0, hashLength)
 | 
					            return formatResult(h).copyOfRange(0, hashLength)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun formatResult(h: Array<ULong>): Array<UByte> {
 | 
					        private fun formatResult(h: Array<ULong>): UByteArray {
 | 
				
			||||||
            return h.map {
 | 
					            return h.map {
 | 
				
			||||||
                arrayOf(
 | 
					                arrayOf(
 | 
				
			||||||
                    (it and 0xFFUL).toUByte(),
 | 
					                    (it and 0xFFUL).toUByte(),
 | 
				
			||||||
@ -222,10 +222,10 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
                )
 | 
					                )
 | 
				
			||||||
            }.flatMap {
 | 
					            }.flatMap {
 | 
				
			||||||
                it.toList()
 | 
					                it.toList()
 | 
				
			||||||
            }.toTypedArray()
 | 
					            }.toUByteArray()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun padToBlock(unpadded: Array<UByte>): Array<UByte> {
 | 
					        private fun padToBlock(unpadded: UByteArray): UByteArray {
 | 
				
			||||||
            if (unpadded.size == BLOCK_BYTES) {
 | 
					            if (unpadded.size == BLOCK_BYTES) {
 | 
				
			||||||
                return unpadded
 | 
					                return unpadded
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -234,7 +234,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
                throw IllegalStateException("Block larger than 128 bytes")
 | 
					                throw IllegalStateException("Block larger than 128 bytes")
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return Array(BLOCK_BYTES) {
 | 
					            return UByteArray(BLOCK_BYTES) {
 | 
				
			||||||
                when (it) {
 | 
					                when (it) {
 | 
				
			||||||
                    in 0 until unpadded.size -> unpadded[it]
 | 
					                    in 0 until unpadded.size -> unpadded[it]
 | 
				
			||||||
                    else -> 0U
 | 
					                    else -> 0U
 | 
				
			||||||
@ -243,21 +243,21 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    @ExperimentalStdlibApi
 | 
					
 | 
				
			||||||
    constructor(
 | 
					    constructor(
 | 
				
			||||||
        key: String?,
 | 
					        key: String?,
 | 
				
			||||||
        requestedHashLenght: Int = 64
 | 
					        requestedHashLenght: Int = 64
 | 
				
			||||||
    ) : this(
 | 
					    ) : this(
 | 
				
			||||||
        (key?.encodeToByteArray()?.map { it.toUByte() }?.toTypedArray() ?: emptyArray<UByte>()),
 | 
					        (key?.encodeToByteArray()?.toUByteArray() ?: ubyteArrayOf()),
 | 
				
			||||||
        requestedHashLenght
 | 
					        requestedHashLenght
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override val MAX_HASH_BYTES: Int = Blake2b.MAX_HASH_BYTES
 | 
					    override val MAX_HASH_BYTES: Int = Blake2bPure.MAX_HASH_BYTES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var h = iv.copyOf()
 | 
					    var h = iv.copyOf()
 | 
				
			||||||
    var counter = BigInteger.ZERO
 | 
					    var counter = BigInteger.ZERO
 | 
				
			||||||
    var bufferCounter = 0
 | 
					    var bufferCounter = 0
 | 
				
			||||||
    var buffer = Array<UByte>(BLOCK_BYTES) { 0U }
 | 
					    var buffer = UByteArray(BLOCK_BYTES) { 0U }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    init {
 | 
					    init {
 | 
				
			||||||
@ -268,7 +268,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun update(data: Array<UByte>) {
 | 
					    override fun update(data: UByteArray) {
 | 
				
			||||||
        if (data.isEmpty()) {
 | 
					        if (data.isEmpty()) {
 | 
				
			||||||
            throw RuntimeException("Updating with empty array is not allowed. If you need empty hash, just call digest without updating")
 | 
					            throw RuntimeException("Updating with empty array is not allowed. If you need empty hash, just call digest without updating")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -276,7 +276,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
        when {
 | 
					        when {
 | 
				
			||||||
            bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
 | 
					            bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
 | 
				
			||||||
            bufferCounter + data.size >= BLOCK_BYTES -> {
 | 
					            bufferCounter + data.size >= BLOCK_BYTES -> {
 | 
				
			||||||
                val chunked = data.chunked(BLOCK_BYTES)
 | 
					                val chunked = data.chunked(BLOCK_BYTES).map { it.toUByteArray() }
 | 
				
			||||||
                chunked.forEach { chunk ->
 | 
					                chunked.forEach { chunk ->
 | 
				
			||||||
                    if (bufferCounter + chunk.size < BLOCK_BYTES) {
 | 
					                    if (bufferCounter + chunk.size < BLOCK_BYTES) {
 | 
				
			||||||
                        appendToBuffer(chunk, bufferCounter)
 | 
					                        appendToBuffer(chunk, bufferCounter)
 | 
				
			||||||
@ -289,7 +289,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
                        )
 | 
					                        )
 | 
				
			||||||
                        counter += BLOCK_BYTES
 | 
					                        counter += BLOCK_BYTES
 | 
				
			||||||
                        consumeBlock(buffer)
 | 
					                        consumeBlock(buffer)
 | 
				
			||||||
                        buffer = Array<UByte>(BLOCK_BYTES) {
 | 
					                        buffer = UByteArray(BLOCK_BYTES) {
 | 
				
			||||||
                            when (it) {
 | 
					                            when (it) {
 | 
				
			||||||
                                in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> {
 | 
					                                in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> {
 | 
				
			||||||
                                    chunk[it + (BLOCK_BYTES - bufferCounter)]
 | 
					                                    chunk[it + (BLOCK_BYTES - bufferCounter)]
 | 
				
			||||||
@ -308,21 +308,21 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    @ExperimentalStdlibApi
 | 
					
 | 
				
			||||||
    override fun update(data: String) {
 | 
					    fun update(data: String) {
 | 
				
			||||||
        update(data.encodeToByteArray().map { it.toUByte() }.toTypedArray())
 | 
					        update(data.encodeToByteArray().toUByteArray())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun appendToBuffer(array: Array<UByte>, start: Int) {
 | 
					    private fun appendToBuffer(array: UByteArray, start: Int) {
 | 
				
			||||||
        array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
 | 
					        array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
 | 
				
			||||||
        bufferCounter += array.size
 | 
					        bufferCounter += array.size
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun consumeBlock(block: Array<UByte>) {
 | 
					    private fun consumeBlock(block: UByteArray) {
 | 
				
			||||||
        h = compress(h, block, counter, false)
 | 
					        h = compress(h, block, counter, false)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun digest(): Array<UByte> {
 | 
					    override fun digest(): UByteArray {
 | 
				
			||||||
        val lastBlockPadded = padToBlock(buffer)
 | 
					        val lastBlockPadded = padToBlock(buffer)
 | 
				
			||||||
        counter += bufferCounter
 | 
					        counter += bufferCounter
 | 
				
			||||||
        compress(h, lastBlockPadded, counter, true)
 | 
					        compress(h, lastBlockPadded, counter, true)
 | 
				
			||||||
@ -333,15 +333,12 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun digestString(): String {
 | 
					 | 
				
			||||||
        return digest().map { it.toString(16) }.joinToString(separator = "")
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun reset() {
 | 
					    private fun reset() {
 | 
				
			||||||
        h = iv.copyOf()
 | 
					        h = iv.copyOf()
 | 
				
			||||||
        counter = BigInteger.ZERO
 | 
					        counter = BigInteger.ZERO
 | 
				
			||||||
        bufferCounter = 0
 | 
					        bufferCounter = 0
 | 
				
			||||||
        buffer = Array<UByte>(BLOCK_BYTES) { 0U }
 | 
					        buffer = UByteArray(BLOCK_BYTES) { 0U }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -16,9 +16,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.ionspin.kotlin.crypto.hash.sha
 | 
					package com.ionspin.kotlin.crypto.hash.sha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.chunked
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.hash.StatelessHash
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.hash.UpdatableHash
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.rotateRight
 | 
					import com.ionspin.kotlin.crypto.util.rotateRight
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -29,13 +26,13 @@ import com.ionspin.kotlin.crypto.util.rotateRight
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ExperimentalUnsignedTypes
 | 
					
 | 
				
			||||||
class Sha256 : UpdatableHash {
 | 
					class Sha256Pure : Sha256 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override val MAX_HASH_BYTES: Int = 32
 | 
					    override val MAX_HASH_BYTES: Int = 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    companion object : StatelessHash {
 | 
					    companion object : StatelessSha256 {
 | 
				
			||||||
        const val BLOCK_SIZE = 512
 | 
					        const val BLOCK_SIZE = 512
 | 
				
			||||||
        const val BLOCK_SIZE_IN_BYTES = 64
 | 
					        const val BLOCK_SIZE_IN_BYTES = 64
 | 
				
			||||||
        const val UINT_MASK = 0xFFFFFFFFU
 | 
					        const val UINT_MASK = 0xFFFFFFFFU
 | 
				
			||||||
@ -66,15 +63,8 @@ class Sha256 : UpdatableHash {
 | 
				
			|||||||
            0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U, 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U
 | 
					            0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U, 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @ExperimentalStdlibApi
 | 
					 | 
				
			||||||
        override fun digest(inputString: String, key: String?, hashLength: Int): Array<UByte> {
 | 
					 | 
				
			||||||
            return digest(
 | 
					 | 
				
			||||||
                inputString.encodeToByteArray().map { it.toUByte() }.toTypedArray(),
 | 
					 | 
				
			||||||
                key?.run { encodeToByteArray().map { it.toUByte() }.toTypedArray() } ?: emptyArray<UByte>(),
 | 
					 | 
				
			||||||
                hashLength)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        override fun digest(inputMessage: Array<UByte>, key: Array<UByte>, hashLength: Int): Array<UByte> {
 | 
					        override fun digest(inputMessage: UByteArray): UByteArray {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var h = iv.copyOf()
 | 
					            var h = iv.copyOf()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -88,7 +78,7 @@ class Sha256 : UpdatableHash {
 | 
				
			|||||||
                .chunked(BLOCK_SIZE_IN_BYTES)
 | 
					                .chunked(BLOCK_SIZE_IN_BYTES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            chunks.forEach { chunk ->
 | 
					            chunks.forEach { chunk ->
 | 
				
			||||||
                val w = expandChunk(chunk)
 | 
					                val w = expandChunk(chunk.toUByteArray())
 | 
				
			||||||
                mix(h, w).copyInto(h)
 | 
					                mix(h, w).copyInto(h)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -128,7 +118,7 @@ class Sha256 : UpdatableHash {
 | 
				
			|||||||
            return (((x and y) xor (x and z) xor (y and z)))
 | 
					            return (((x and y) xor (x and z) xor (y and z)))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun expandChunk(chunk: Array<UByte>): Array<UInt> {
 | 
					        private fun expandChunk(chunk: UByteArray): Array<UInt> {
 | 
				
			||||||
            val w = Array<UInt>(BLOCK_SIZE_IN_BYTES) {
 | 
					            val w = Array<UInt>(BLOCK_SIZE_IN_BYTES) {
 | 
				
			||||||
                when (it) {
 | 
					                when (it) {
 | 
				
			||||||
                    in 0 until 16 -> {
 | 
					                    in 0 until 16 -> {
 | 
				
			||||||
@ -188,7 +178,7 @@ class Sha256 : UpdatableHash {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fun createExpansionArray(originalSizeInBytes: Int): Array<UByte> {
 | 
					        fun createExpansionArray(originalSizeInBytes: Int): UByteArray {
 | 
				
			||||||
            val originalMessageSizeInBits = originalSizeInBytes * 8
 | 
					            val originalMessageSizeInBits = originalSizeInBytes * 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -198,7 +188,7 @@ class Sha256 : UpdatableHash {
 | 
				
			|||||||
                0 -> 0
 | 
					                0 -> 0
 | 
				
			||||||
                else -> (BLOCK_SIZE - expandedRemainderOf512) / 8
 | 
					                else -> (BLOCK_SIZE - expandedRemainderOf512) / 8
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            val expansionArray = Array<UByte>(zeroAddAmount + 1) {
 | 
					            val expansionArray = UByteArray(zeroAddAmount + 1) {
 | 
				
			||||||
                when (it) {
 | 
					                when (it) {
 | 
				
			||||||
                    0 -> 0b10000000U
 | 
					                    0 -> 0b10000000U
 | 
				
			||||||
                    else -> 0U
 | 
					                    else -> 0U
 | 
				
			||||||
@ -207,9 +197,9 @@ class Sha256 : UpdatableHash {
 | 
				
			|||||||
            return expansionArray
 | 
					            return expansionArray
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun ULong.toPaddedByteArray(): Array<UByte> {
 | 
					        private fun ULong.toPaddedByteArray(): UByteArray {
 | 
				
			||||||
            val byteMask = BYTE_MASK_FROM_ULONG
 | 
					            val byteMask = BYTE_MASK_FROM_ULONG
 | 
				
			||||||
            return Array(8) {
 | 
					            return UByteArray(8) {
 | 
				
			||||||
                when (it) {
 | 
					                when (it) {
 | 
				
			||||||
                    7 -> (this and byteMask).toUByte()
 | 
					                    7 -> (this and byteMask).toUByte()
 | 
				
			||||||
                    6 -> ((this shr 8) and byteMask).toUByte()
 | 
					                    6 -> ((this shr 8) and byteMask).toUByte()
 | 
				
			||||||
@ -224,9 +214,9 @@ class Sha256 : UpdatableHash {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun UInt.toPaddedByteArray(): Array<UByte> {
 | 
					        private fun UInt.toPaddedByteArray(): UByteArray {
 | 
				
			||||||
            val byteMask = BYTE_MASK_FROM_UINT
 | 
					            val byteMask = BYTE_MASK_FROM_UINT
 | 
				
			||||||
            return Array(4) {
 | 
					            return UByteArray(4) {
 | 
				
			||||||
                when (it) {
 | 
					                when (it) {
 | 
				
			||||||
                    3 -> (this and byteMask).toUByte()
 | 
					                    3 -> (this and byteMask).toUByte()
 | 
				
			||||||
                    2 -> ((this shr 8) and byteMask).toUByte()
 | 
					                    2 -> ((this shr 8) and byteMask).toUByte()
 | 
				
			||||||
@ -242,14 +232,14 @@ class Sha256 : UpdatableHash {
 | 
				
			|||||||
    var h = iv.copyOf()
 | 
					    var h = iv.copyOf()
 | 
				
			||||||
    var counter = 0
 | 
					    var counter = 0
 | 
				
			||||||
    var bufferCounter = 0
 | 
					    var bufferCounter = 0
 | 
				
			||||||
    var buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) { 0U }
 | 
					    var buffer = UByteArray(BLOCK_SIZE_IN_BYTES) { 0U }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ExperimentalStdlibApi
 | 
					
 | 
				
			||||||
    override fun update(data: String) {
 | 
					    fun update(data: String) {
 | 
				
			||||||
        return update(data.encodeToByteArray().map { it.toUByte() }.toTypedArray())
 | 
					        return update(data.encodeToByteArray().toUByteArray())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun update(data: Array<UByte>) {
 | 
					    override fun update(data: UByteArray) {
 | 
				
			||||||
        if (data.isEmpty()) {
 | 
					        if (data.isEmpty()) {
 | 
				
			||||||
            throw RuntimeException("Updating with empty array is not allowed. If you need empty hash, just call digest without updating")
 | 
					            throw RuntimeException("Updating with empty array is not allowed. If you need empty hash, just call digest without updating")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -260,9 +250,9 @@ class Sha256 : UpdatableHash {
 | 
				
			|||||||
                val chunked = data.chunked(BLOCK_SIZE_IN_BYTES)
 | 
					                val chunked = data.chunked(BLOCK_SIZE_IN_BYTES)
 | 
				
			||||||
                chunked.forEach { chunk ->
 | 
					                chunked.forEach { chunk ->
 | 
				
			||||||
                    if (bufferCounter + chunk.size < BLOCK_SIZE_IN_BYTES) {
 | 
					                    if (bufferCounter + chunk.size < BLOCK_SIZE_IN_BYTES) {
 | 
				
			||||||
                        appendToBuffer(chunk, bufferCounter)
 | 
					                        appendToBuffer(chunk.toUByteArray(), bufferCounter)
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        chunk.copyInto(
 | 
					                        chunk.toUByteArray().copyInto(
 | 
				
			||||||
                            destination = buffer,
 | 
					                            destination = buffer,
 | 
				
			||||||
                            destinationOffset = bufferCounter,
 | 
					                            destinationOffset = bufferCounter,
 | 
				
			||||||
                            startIndex = 0,
 | 
					                            startIndex = 0,
 | 
				
			||||||
@ -270,7 +260,7 @@ class Sha256 : UpdatableHash {
 | 
				
			|||||||
                        )
 | 
					                        )
 | 
				
			||||||
                        counter += BLOCK_SIZE_IN_BYTES
 | 
					                        counter += BLOCK_SIZE_IN_BYTES
 | 
				
			||||||
                        consumeBlock(buffer)
 | 
					                        consumeBlock(buffer)
 | 
				
			||||||
                        buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) {
 | 
					                        buffer = UByteArray(BLOCK_SIZE_IN_BYTES) {
 | 
				
			||||||
                            when (it) {
 | 
					                            when (it) {
 | 
				
			||||||
                                in (0 until (chunk.size - (BLOCK_SIZE_IN_BYTES - bufferCounter))) -> {
 | 
					                                in (0 until (chunk.size - (BLOCK_SIZE_IN_BYTES - bufferCounter))) -> {
 | 
				
			||||||
                                    chunk[it + (BLOCK_SIZE_IN_BYTES - bufferCounter)]
 | 
					                                    chunk[it + (BLOCK_SIZE_IN_BYTES - bufferCounter)]
 | 
				
			||||||
@ -289,18 +279,18 @@ class Sha256 : UpdatableHash {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun consumeBlock(block: Array<UByte>) {
 | 
					    private fun consumeBlock(block: UByteArray) {
 | 
				
			||||||
        val w = expandChunk(block)
 | 
					        val w = expandChunk(block)
 | 
				
			||||||
        mix(h, w).copyInto(h)
 | 
					        mix(h, w).copyInto(h)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun digest(): Array<UByte> {
 | 
					    override fun digest(): UByteArray {
 | 
				
			||||||
        val length = counter + bufferCounter
 | 
					        val length = counter + bufferCounter
 | 
				
			||||||
        val expansionArray = createExpansionArray(length)
 | 
					        val expansionArray = createExpansionArray(length)
 | 
				
			||||||
        val finalBlock =
 | 
					        val finalBlock =
 | 
				
			||||||
            buffer.copyOfRange(0, bufferCounter) + expansionArray + (length * 8).toULong().toPaddedByteArray()
 | 
					            buffer.copyOfRange(0, bufferCounter) + expansionArray + (length * 8).toULong().toPaddedByteArray()
 | 
				
			||||||
        finalBlock.chunked(BLOCK_SIZE_IN_BYTES).forEach {
 | 
					        finalBlock.chunked(BLOCK_SIZE_IN_BYTES).forEach {
 | 
				
			||||||
            consumeBlock(it)
 | 
					            consumeBlock(it.toUByteArray())
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -315,11 +305,7 @@ class Sha256 : UpdatableHash {
 | 
				
			|||||||
        return digest
 | 
					        return digest
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun digestString(): String {
 | 
					    private fun appendToBuffer(array: UByteArray, start: Int) {
 | 
				
			||||||
        return digest().map { it.toString(16) }.joinToString(separator = "")
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private fun appendToBuffer(array: Array<UByte>, start: Int) {
 | 
					 | 
				
			||||||
        array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
 | 
					        array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
 | 
				
			||||||
        bufferCounter += array.size
 | 
					        bufferCounter += array.size
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -16,9 +16,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.ionspin.kotlin.crypto.hash.sha
 | 
					package com.ionspin.kotlin.crypto.hash.sha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.chunked
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.hash.StatelessHash
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.hash.UpdatableHash
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.rotateRight
 | 
					import com.ionspin.kotlin.crypto.util.rotateRight
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -27,12 +24,12 @@ import com.ionspin.kotlin.crypto.util.rotateRight
 | 
				
			|||||||
 * on 18-Jul-2019
 | 
					 * on 18-Jul-2019
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ExperimentalUnsignedTypes
 | 
					
 | 
				
			||||||
class Sha512 : UpdatableHash {
 | 
					class Sha512Pure : Sha512 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override val MAX_HASH_BYTES: Int = 32
 | 
					    override val MAX_HASH_BYTES: Int = 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    companion object : StatelessHash {
 | 
					    companion object : StatelessSha512 {
 | 
				
			||||||
        const val BLOCK_SIZE = 1024
 | 
					        const val BLOCK_SIZE = 1024
 | 
				
			||||||
        const val BLOCK_SIZE_IN_BYTES = 128
 | 
					        const val BLOCK_SIZE_IN_BYTES = 128
 | 
				
			||||||
        const val CHUNK_SIZE = 80
 | 
					        const val CHUNK_SIZE = 80
 | 
				
			||||||
@ -134,16 +131,8 @@ class Sha512 : UpdatableHash {
 | 
				
			|||||||
            0x5be0cd19137e2179UL
 | 
					            0x5be0cd19137e2179UL
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @ExperimentalStdlibApi
 | 
					 | 
				
			||||||
        override fun digest(inputString: String, key: String?, hashLength: Int): Array<UByte> {
 | 
					 | 
				
			||||||
            return digest(
 | 
					 | 
				
			||||||
                inputString.encodeToByteArray().map { it.toUByte() }.toTypedArray(),
 | 
					 | 
				
			||||||
                key?.run { encodeToByteArray().map { it.toUByte() }.toTypedArray() } ?: emptyArray<UByte>(),
 | 
					 | 
				
			||||||
                hashLength = hashLength
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        override fun digest(inputMessage: Array<UByte>, key: Array<UByte>, hashLength: Int): Array<UByte> {
 | 
					        override fun digest(inputMessage: UByteArray): UByteArray {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var h = iv.copyOf()
 | 
					            var h = iv.copyOf()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -155,7 +144,7 @@ class Sha512 : UpdatableHash {
 | 
				
			|||||||
                )
 | 
					                )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            chunks.forEach { chunk ->
 | 
					            chunks.forEach { chunk ->
 | 
				
			||||||
                val w = expandChunk(chunk)
 | 
					                val w = expandChunk(chunk.toUByteArray())
 | 
				
			||||||
                mix(h, w)
 | 
					                mix(h, w)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -196,7 +185,7 @@ class Sha512 : UpdatableHash {
 | 
				
			|||||||
            return ((x and y) xor (x and z) xor (y and z))
 | 
					            return ((x and y) xor (x and z) xor (y and z))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun expandChunk(chunk: Array<UByte>): Array<ULong> {
 | 
					        private fun expandChunk(chunk: UByteArray): Array<ULong> {
 | 
				
			||||||
            val w = Array<ULong>(CHUNK_SIZE) {
 | 
					            val w = Array<ULong>(CHUNK_SIZE) {
 | 
				
			||||||
                when (it) {
 | 
					                when (it) {
 | 
				
			||||||
                    in 0 until 16 -> {
 | 
					                    in 0 until 16 -> {
 | 
				
			||||||
@ -259,7 +248,7 @@ class Sha512 : UpdatableHash {
 | 
				
			|||||||
            return h
 | 
					            return h
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fun createExpansionArray(originalSizeInBytes: Int): Array<UByte> {
 | 
					        fun createExpansionArray(originalSizeInBytes: Int): UByteArray {
 | 
				
			||||||
            val originalMessageSizeInBits = originalSizeInBytes * 8
 | 
					            val originalMessageSizeInBits = originalSizeInBytes * 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            val expandedRemainderOf1024 = (originalMessageSizeInBits + 129) % BLOCK_SIZE
 | 
					            val expandedRemainderOf1024 = (originalMessageSizeInBits + 129) % BLOCK_SIZE
 | 
				
			||||||
@ -267,7 +256,7 @@ class Sha512 : UpdatableHash {
 | 
				
			|||||||
                0 -> 0
 | 
					                0 -> 0
 | 
				
			||||||
                else -> (BLOCK_SIZE - expandedRemainderOf1024) / 8
 | 
					                else -> (BLOCK_SIZE - expandedRemainderOf1024) / 8
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            val expansionArray = Array<UByte>(zeroAddAmount + 1) {
 | 
					            val expansionArray = UByteArray(zeroAddAmount + 1) {
 | 
				
			||||||
                when (it) {
 | 
					                when (it) {
 | 
				
			||||||
                    0 -> 0b10000000U
 | 
					                    0 -> 0b10000000U
 | 
				
			||||||
                    else -> 0U
 | 
					                    else -> 0U
 | 
				
			||||||
@ -277,10 +266,10 @@ class Sha512 : UpdatableHash {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun ULong.toPaddedByteArray(): Array<UByte> {
 | 
					        private fun ULong.toPaddedByteArray(): UByteArray {
 | 
				
			||||||
            val byteMask = 0xFFUL
 | 
					            val byteMask = 0xFFUL
 | 
				
			||||||
            //Ignore messages longer than 64 bits for now
 | 
					            //Ignore messages longer than 64 bits for now
 | 
				
			||||||
            return Array(8) {
 | 
					            return UByteArray(8) {
 | 
				
			||||||
                when (it) {
 | 
					                when (it) {
 | 
				
			||||||
                    7 -> (this and byteMask).toUByte()
 | 
					                    7 -> (this and byteMask).toUByte()
 | 
				
			||||||
                    6 -> ((this shr 8) and byteMask).toUByte()
 | 
					                    6 -> ((this shr 8) and byteMask).toUByte()
 | 
				
			||||||
@ -295,10 +284,10 @@ class Sha512 : UpdatableHash {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private fun ULong.toPadded128BitByteArray(): Array<UByte> {
 | 
					        private fun ULong.toPadded128BitByteArray(): UByteArray {
 | 
				
			||||||
            val byteMask = 0xFFUL
 | 
					            val byteMask = 0xFFUL
 | 
				
			||||||
            //Ignore messages longer than 64 bits for now
 | 
					            //Ignore messages longer than 64 bits for now
 | 
				
			||||||
            return Array(16) {
 | 
					            return UByteArray(16) {
 | 
				
			||||||
                when (it) {
 | 
					                when (it) {
 | 
				
			||||||
                    15 -> (this and byteMask).toUByte()
 | 
					                    15 -> (this and byteMask).toUByte()
 | 
				
			||||||
                    14 -> ((this shr 8) and byteMask).toUByte()
 | 
					                    14 -> ((this shr 8) and byteMask).toUByte()
 | 
				
			||||||
@ -317,14 +306,14 @@ class Sha512 : UpdatableHash {
 | 
				
			|||||||
    var h = iv.copyOf()
 | 
					    var h = iv.copyOf()
 | 
				
			||||||
    var counter = 0
 | 
					    var counter = 0
 | 
				
			||||||
    var bufferCounter = 0
 | 
					    var bufferCounter = 0
 | 
				
			||||||
    var buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) { 0U }
 | 
					    var buffer = UByteArray(BLOCK_SIZE_IN_BYTES) { 0U }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ExperimentalStdlibApi
 | 
					
 | 
				
			||||||
    override fun update(data: String) {
 | 
					    fun update(data: String) {
 | 
				
			||||||
        return update(data.encodeToByteArray().map { it.toUByte() }.toTypedArray())
 | 
					        return update(data.encodeToByteArray().toUByteArray())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun update(data: Array<UByte>) {
 | 
					    override fun update(data: UByteArray) {
 | 
				
			||||||
        if (data.isEmpty()) {
 | 
					        if (data.isEmpty()) {
 | 
				
			||||||
            throw RuntimeException("Updating with empty array is not allowed. If you need empty hash, just call digest without updating")
 | 
					            throw RuntimeException("Updating with empty array is not allowed. If you need empty hash, just call digest without updating")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -335,9 +324,9 @@ class Sha512 : UpdatableHash {
 | 
				
			|||||||
                val chunked = data.chunked(BLOCK_SIZE_IN_BYTES)
 | 
					                val chunked = data.chunked(BLOCK_SIZE_IN_BYTES)
 | 
				
			||||||
                chunked.forEach { chunk ->
 | 
					                chunked.forEach { chunk ->
 | 
				
			||||||
                    if (bufferCounter + chunk.size < BLOCK_SIZE_IN_BYTES) {
 | 
					                    if (bufferCounter + chunk.size < BLOCK_SIZE_IN_BYTES) {
 | 
				
			||||||
                        appendToBuffer(chunk, bufferCounter)
 | 
					                        appendToBuffer(chunk.toUByteArray(), bufferCounter)
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        chunk.copyInto(
 | 
					                        chunk.toUByteArray().copyInto(
 | 
				
			||||||
                            destination = buffer,
 | 
					                            destination = buffer,
 | 
				
			||||||
                            destinationOffset = bufferCounter,
 | 
					                            destinationOffset = bufferCounter,
 | 
				
			||||||
                            startIndex = 0,
 | 
					                            startIndex = 0,
 | 
				
			||||||
@ -345,7 +334,7 @@ class Sha512 : UpdatableHash {
 | 
				
			|||||||
                        )
 | 
					                        )
 | 
				
			||||||
                        counter += BLOCK_SIZE_IN_BYTES
 | 
					                        counter += BLOCK_SIZE_IN_BYTES
 | 
				
			||||||
                        consumeBlock(buffer)
 | 
					                        consumeBlock(buffer)
 | 
				
			||||||
                        buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) {
 | 
					                        buffer = UByteArray(BLOCK_SIZE_IN_BYTES) {
 | 
				
			||||||
                            when (it) {
 | 
					                            when (it) {
 | 
				
			||||||
                                in (0 until (chunk.size - (BLOCK_SIZE_IN_BYTES - bufferCounter))) -> {
 | 
					                                in (0 until (chunk.size - (BLOCK_SIZE_IN_BYTES - bufferCounter))) -> {
 | 
				
			||||||
                                    chunk[it + (BLOCK_SIZE_IN_BYTES - bufferCounter)]
 | 
					                                    chunk[it + (BLOCK_SIZE_IN_BYTES - bufferCounter)]
 | 
				
			||||||
@ -364,18 +353,18 @@ class Sha512 : UpdatableHash {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun consumeBlock(block: Array<UByte>) {
 | 
					    private fun consumeBlock(block: UByteArray) {
 | 
				
			||||||
        val w = expandChunk(block)
 | 
					        val w = expandChunk(block)
 | 
				
			||||||
        mix(h, w).copyInto(h)
 | 
					        mix(h, w).copyInto(h)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun digest(): Array<UByte> {
 | 
					    override fun digest(): UByteArray {
 | 
				
			||||||
        val length = counter + bufferCounter
 | 
					        val length = counter + bufferCounter
 | 
				
			||||||
        val expansionArray = createExpansionArray(length)
 | 
					        val expansionArray = createExpansionArray(length)
 | 
				
			||||||
        val finalBlock =
 | 
					        val finalBlock =
 | 
				
			||||||
            buffer.copyOfRange(0, bufferCounter) + expansionArray + (length * 8).toULong().toPadded128BitByteArray()
 | 
					            buffer.copyOfRange(0, bufferCounter) + expansionArray + (length * 8).toULong().toPadded128BitByteArray()
 | 
				
			||||||
        finalBlock.chunked(BLOCK_SIZE_IN_BYTES).forEach {
 | 
					        finalBlock.chunked(BLOCK_SIZE_IN_BYTES).forEach {
 | 
				
			||||||
            consumeBlock(it)
 | 
					            consumeBlock(it.toUByteArray())
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -390,11 +379,7 @@ class Sha512 : UpdatableHash {
 | 
				
			|||||||
        return digest
 | 
					        return digest
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun digestString(): String {
 | 
					    private fun appendToBuffer(array: UByteArray, start: Int) {
 | 
				
			||||||
        return digest().map { it.toString(16) }.joinToString(separator = "")
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private fun appendToBuffer(array: Array<UByte>, start: Int) {
 | 
					 | 
				
			||||||
        array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
 | 
					        array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
 | 
				
			||||||
        bufferCounter += array.size
 | 
					        bufferCounter += array.size
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -1,377 +1,10 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 *    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", "EXPERIMENTAL_UNSIGNED_LITERALS")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package com.ionspin.kotlin.crypto.keyderivation.argon2
 | 
					package com.ionspin.kotlin.crypto.keyderivation.argon2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.ionspin.kotlin.bignum.integer.toBigInteger
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.keyderivation.KeyDerivationFunction
 | 
					import com.ionspin.kotlin.crypto.keyderivation.KeyDerivationFunction
 | 
				
			||||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.argonBlake2bArbitraryLenghtHash
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.compressionFunctionG
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.validateArgonParameters
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToUInt
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.hexColumsPrint
 | 
					 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.toLittleEndianUByteArray
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Created by Ugljesa Jovanovic
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 * ugljesa.jovanovic@ionspin.com
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 * on 16-May-2020
 | 
					 * on 24-May-2020
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					interface Argon2 : KeyDerivationFunction
 | 
				
			||||||
enum class ArgonType(val typeId: Int) {
 | 
					 | 
				
			||||||
    Argon2d(0), Argon2i(1), Argon2id(2)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
data class SegmentPosition(
 | 
					 | 
				
			||||||
    val iteration: Int,
 | 
					 | 
				
			||||||
    val lane: Int,
 | 
					 | 
				
			||||||
    val slice: Int
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@ExperimentalStdlibApi
 | 
					 | 
				
			||||||
class Argon2(
 | 
					 | 
				
			||||||
    private val password: Array<UByte>,
 | 
					 | 
				
			||||||
    private val salt: Array<UByte> = emptyArray(),
 | 
					 | 
				
			||||||
    private val parallelism: Int = 1,
 | 
					 | 
				
			||||||
    private val tagLength: UInt = 64U,
 | 
					 | 
				
			||||||
    requestedMemorySize: UInt = 0U,
 | 
					 | 
				
			||||||
    private val numberOfIterations: UInt = 1U,
 | 
					 | 
				
			||||||
    private val key: Array<UByte> = emptyArray(),
 | 
					 | 
				
			||||||
    private val associatedData: Array<UByte> = emptyArray(),
 | 
					 | 
				
			||||||
    private val argonType: ArgonType = ArgonType.Argon2id
 | 
					 | 
				
			||||||
) : KeyDerivationFunction {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    constructor(
 | 
					 | 
				
			||||||
        password: String,
 | 
					 | 
				
			||||||
        salt: String = "",
 | 
					 | 
				
			||||||
        parallelism: Int = 1,
 | 
					 | 
				
			||||||
        tagLength: UInt = 64U,
 | 
					 | 
				
			||||||
        requestedMemorySize: UInt = 0U,
 | 
					 | 
				
			||||||
        numberOfIterations: UInt = 10U,
 | 
					 | 
				
			||||||
        key: String = "",
 | 
					 | 
				
			||||||
        associatedData: String = "",
 | 
					 | 
				
			||||||
        argonType: ArgonType = ArgonType.Argon2id
 | 
					 | 
				
			||||||
    ) : this(
 | 
					 | 
				
			||||||
        password.encodeToByteArray().map { it.toUByte() }.toList().toTypedArray(),
 | 
					 | 
				
			||||||
        salt.encodeToByteArray().map { it.toUByte() }.toList().toTypedArray(),
 | 
					 | 
				
			||||||
        parallelism,
 | 
					 | 
				
			||||||
        tagLength,
 | 
					 | 
				
			||||||
        requestedMemorySize,
 | 
					 | 
				
			||||||
        numberOfIterations,
 | 
					 | 
				
			||||||
        key.encodeToByteArray().map { it.toUByte() }.toList().toTypedArray(),
 | 
					 | 
				
			||||||
        associatedData.encodeToByteArray().map { it.toUByte() }.toList().toTypedArray(),
 | 
					 | 
				
			||||||
        argonType
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    init {
 | 
					 | 
				
			||||||
        validateArgonParameters(
 | 
					 | 
				
			||||||
            password,
 | 
					 | 
				
			||||||
            salt,
 | 
					 | 
				
			||||||
            parallelism,
 | 
					 | 
				
			||||||
            tagLength,
 | 
					 | 
				
			||||||
            requestedMemorySize,
 | 
					 | 
				
			||||||
            numberOfIterations,
 | 
					 | 
				
			||||||
            key,
 | 
					 | 
				
			||||||
            associatedData,
 | 
					 | 
				
			||||||
            argonType
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //We support only the latest version
 | 
					 | 
				
			||||||
    private val versionNumber: UInt = 0x13U
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //Use either requested memory size, or default, or throw exception if the requested amount is less than 8*parallelism
 | 
					 | 
				
			||||||
    private val memorySize = if (requestedMemorySize == 0U) {
 | 
					 | 
				
			||||||
        ((8 * parallelism) * 2).toUInt()
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        requestedMemorySize
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    private val blockCount = (memorySize / (4U * parallelism.toUInt())) * (4U * parallelism.toUInt())
 | 
					 | 
				
			||||||
    private val columnCount = (blockCount / parallelism.toUInt()).toInt()
 | 
					 | 
				
			||||||
    private val segmentLength = columnCount / 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private val useIndependentAddressing = argonType == ArgonType.Argon2id || argonType == ArgonType.Argon2i
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // State
 | 
					 | 
				
			||||||
    private val matrix = Array(parallelism) {
 | 
					 | 
				
			||||||
        Array(columnCount) {
 | 
					 | 
				
			||||||
            Array<UByte>(1024) { 0U }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private fun clearMatrix() {
 | 
					 | 
				
			||||||
        matrix.forEachIndexed { laneIndex, lane ->
 | 
					 | 
				
			||||||
            lane.forEachIndexed { columnIndex, block ->
 | 
					 | 
				
			||||||
                block.forEachIndexed { byteIndex, byte ->
 | 
					 | 
				
			||||||
                    matrix[laneIndex][columnIndex][byteIndex] = 0U
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private fun populateAddressBlock(
 | 
					 | 
				
			||||||
        iteration: Int,
 | 
					 | 
				
			||||||
        slice: Int,
 | 
					 | 
				
			||||||
        lane: Int,
 | 
					 | 
				
			||||||
        addressBlock: Array<UByte>,
 | 
					 | 
				
			||||||
        addressCounter: ULong
 | 
					 | 
				
			||||||
    ): Array<UByte> {
 | 
					 | 
				
			||||||
        //Calculate first pass
 | 
					 | 
				
			||||||
        val firstPass = compressionFunctionG(
 | 
					 | 
				
			||||||
            Array<UByte>(1024) { 0U },
 | 
					 | 
				
			||||||
            iteration.toULong().toLittleEndianUByteArray() +
 | 
					 | 
				
			||||||
                    lane.toULong().toLittleEndianUByteArray() +
 | 
					 | 
				
			||||||
                    slice.toULong().toLittleEndianUByteArray() +
 | 
					 | 
				
			||||||
                    blockCount.toULong().toLittleEndianUByteArray() +
 | 
					 | 
				
			||||||
                    numberOfIterations.toULong().toLittleEndianUByteArray() +
 | 
					 | 
				
			||||||
                    argonType.typeId.toULong().toLittleEndianUByteArray() +
 | 
					 | 
				
			||||||
                    addressCounter.toLittleEndianUByteArray() +
 | 
					 | 
				
			||||||
                    Array<UByte>(968) { 0U },
 | 
					 | 
				
			||||||
            addressBlock,
 | 
					 | 
				
			||||||
            false
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        val secondPass = compressionFunctionG(
 | 
					 | 
				
			||||||
            Array<UByte>(1024) { 0U },
 | 
					 | 
				
			||||||
            firstPass,
 | 
					 | 
				
			||||||
            firstPass,
 | 
					 | 
				
			||||||
            false
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        return secondPass
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private fun computeReferenceBlockIndexes(
 | 
					 | 
				
			||||||
        iteration: Int,
 | 
					 | 
				
			||||||
        slice: Int,
 | 
					 | 
				
			||||||
        lane: Int,
 | 
					 | 
				
			||||||
        column: Int,
 | 
					 | 
				
			||||||
        addressBlock: Array<UByte>?
 | 
					 | 
				
			||||||
    ): Pair<Int, Int> {
 | 
					 | 
				
			||||||
        val segmentIndex = (column % segmentLength)
 | 
					 | 
				
			||||||
        val independentIndex = segmentIndex % 128 // 128 is the number of addresses in address block
 | 
					 | 
				
			||||||
        val (j1, j2) = when (argonType) {
 | 
					 | 
				
			||||||
            ArgonType.Argon2d -> {
 | 
					 | 
				
			||||||
                val previousBlock = if (column == 0) {
 | 
					 | 
				
			||||||
                    matrix[lane][columnCount - 1] //Get last block in the SAME lane
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    matrix[lane][column - 1]
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                val first32Bit = previousBlock.sliceArray(0 until 4).fromLittleEndianArrayToUInt()
 | 
					 | 
				
			||||||
                val second32Bit = previousBlock.sliceArray(4 until 8).fromLittleEndianArrayToUInt()
 | 
					 | 
				
			||||||
                Pair(first32Bit, second32Bit)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            ArgonType.Argon2i -> {
 | 
					 | 
				
			||||||
                val selectedAddressBlock = addressBlock!!.sliceArray((independentIndex * 8) until (independentIndex * 8) + 8)
 | 
					 | 
				
			||||||
                val first32Bit = selectedAddressBlock.sliceArray(0 until 4).fromLittleEndianArrayToUInt()
 | 
					 | 
				
			||||||
                val second32Bit = selectedAddressBlock.sliceArray(4 until 8).fromLittleEndianArrayToUInt()
 | 
					 | 
				
			||||||
                Pair(first32Bit, second32Bit)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            ArgonType.Argon2id -> {
 | 
					 | 
				
			||||||
                if (iteration == 0 && (slice == 0 || slice == 1)) {
 | 
					 | 
				
			||||||
                    val selectedAddressBlock =
 | 
					 | 
				
			||||||
                        addressBlock!!.sliceArray((independentIndex * 8) until (independentIndex * 8) + 8)
 | 
					 | 
				
			||||||
                    val first32Bit = selectedAddressBlock.sliceArray(0 until 4).fromLittleEndianArrayToUInt()
 | 
					 | 
				
			||||||
                    val second32Bit = selectedAddressBlock.sliceArray(4 until 8).fromLittleEndianArrayToUInt()
 | 
					 | 
				
			||||||
                    Pair(first32Bit, second32Bit)
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    val previousBlock = if (column == 0) {
 | 
					 | 
				
			||||||
                        matrix[lane][columnCount - 1] //Get last block in the SAME lane
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        matrix[lane][column - 1]
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    val first32Bit = previousBlock.sliceArray(0 until 4).fromLittleEndianArrayToUInt()
 | 
					 | 
				
			||||||
                    val second32Bit = previousBlock.sliceArray(4 until 8).fromLittleEndianArrayToUInt()
 | 
					 | 
				
			||||||
                    Pair(first32Bit, second32Bit)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //If this is first iteration and first slice, block is taken from the current lane
 | 
					 | 
				
			||||||
        val l = if (iteration == 0 && slice == 0) {
 | 
					 | 
				
			||||||
            lane
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            (j2.toBigInteger() % parallelism).intValue()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        val referenceAreaSize = if (iteration == 0) {
 | 
					 | 
				
			||||||
            if (slice == 0) {
 | 
					 | 
				
			||||||
                //All indices except the previous
 | 
					 | 
				
			||||||
                segmentIndex - 1
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                if (lane == l) {
 | 
					 | 
				
			||||||
                    //Same lane
 | 
					 | 
				
			||||||
                    column - 1
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    slice * (columnCount / 4) + if (segmentIndex == 0) { // Check if column is first block of the SEGMENT
 | 
					 | 
				
			||||||
                        -1
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        0
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            if (lane == l) {
 | 
					 | 
				
			||||||
                columnCount - (columnCount / 4) + (segmentIndex - 1)
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                columnCount - (columnCount / 4) + if (segmentIndex == 0) {
 | 
					 | 
				
			||||||
                    -1
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    0
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        val x = (j1.toULong() * j1) shr 32
 | 
					 | 
				
			||||||
        val y = (referenceAreaSize.toULong() * x) shr 32
 | 
					 | 
				
			||||||
        val z = referenceAreaSize.toULong() - 1U - y
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        val startPosition = if (iteration == 0) {
 | 
					 | 
				
			||||||
            0
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            if (slice == 3) {
 | 
					 | 
				
			||||||
                0
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                (slice + 1) * segmentLength
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        val absolutePosition = (startPosition + z.toInt()) % columnCount
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return Pair(l, absolutePosition)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override fun derive(): Array<UByte> {
 | 
					 | 
				
			||||||
        val h0 = Blake2b.digest(
 | 
					 | 
				
			||||||
            parallelism.toUInt()
 | 
					 | 
				
			||||||
                .toLittleEndianUByteArray() + tagLength.toLittleEndianUByteArray() + memorySize.toLittleEndianUByteArray() +
 | 
					 | 
				
			||||||
                    numberOfIterations.toLittleEndianUByteArray() + versionNumber.toLittleEndianUByteArray() + argonType.typeId.toUInt()
 | 
					 | 
				
			||||||
                .toLittleEndianUByteArray() +
 | 
					 | 
				
			||||||
                    password.size.toUInt().toLittleEndianUByteArray() + password +
 | 
					 | 
				
			||||||
                    salt.size.toUInt().toLittleEndianUByteArray() + salt +
 | 
					 | 
				
			||||||
                    key.size.toUInt().toLittleEndianUByteArray() + key +
 | 
					 | 
				
			||||||
                    associatedData.size.toUInt().toLittleEndianUByteArray() + associatedData
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //Compute B[i][0]
 | 
					 | 
				
			||||||
        for (i in 0 until parallelism.toInt()) {
 | 
					 | 
				
			||||||
            matrix[i][0] =
 | 
					 | 
				
			||||||
                argonBlake2bArbitraryLenghtHash(
 | 
					 | 
				
			||||||
                    h0 + 0.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray(),
 | 
					 | 
				
			||||||
                    1024U
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //Compute B[i][1]
 | 
					 | 
				
			||||||
        for (i in 0 until parallelism.toInt()) {
 | 
					 | 
				
			||||||
            matrix[i][1] =
 | 
					 | 
				
			||||||
                argonBlake2bArbitraryLenghtHash(
 | 
					 | 
				
			||||||
                    h0 + 1.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray(),
 | 
					 | 
				
			||||||
                    1024U
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        executeArgonWithSingleThread()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        val result = matrix.foldIndexed(emptyArray<UByte>()) { lane, acc, laneArray ->
 | 
					 | 
				
			||||||
            if (acc.size == 0) {
 | 
					 | 
				
			||||||
                acc + laneArray[columnCount - 1] // add last element in first lane to the accumulator
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                // For each element in our accumulator, xor it with an appropriate element from the last column in current lane (from 1 to `parallelism`)
 | 
					 | 
				
			||||||
                acc.mapIndexed { index, it -> it xor laneArray[columnCount - 1][index] }
 | 
					 | 
				
			||||||
                    .toTypedArray()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        //Hash the xored last blocks
 | 
					 | 
				
			||||||
        val hash = argonBlake2bArbitraryLenghtHash(result, tagLength)
 | 
					 | 
				
			||||||
        clearMatrix()
 | 
					 | 
				
			||||||
        return hash
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private fun executeArgonWithSingleThread() {
 | 
					 | 
				
			||||||
        for (iteration in 0 until numberOfIterations.toInt()) {
 | 
					 | 
				
			||||||
            for (slice in 0 until 4) {
 | 
					 | 
				
			||||||
                for (lane in 0 until parallelism) {
 | 
					 | 
				
			||||||
                    val segmentPosition = SegmentPosition(iteration, lane, slice)
 | 
					 | 
				
			||||||
                    processSegment(segmentPosition)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private fun processSegment(segmentPosition: SegmentPosition) {
 | 
					 | 
				
			||||||
        val iteration = segmentPosition.iteration
 | 
					 | 
				
			||||||
        val slice = segmentPosition.slice
 | 
					 | 
				
			||||||
        val lane = segmentPosition.lane
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var addressBlock: Array<UByte>? = null
 | 
					 | 
				
			||||||
        var addressCounter = 1UL //Starts from 1 in each segment as defined by the spec
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //Generate initial segment address block
 | 
					 | 
				
			||||||
        if (useIndependentAddressing) {
 | 
					 | 
				
			||||||
            addressBlock = Array<UByte>(1024) {
 | 
					 | 
				
			||||||
                0U
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock, addressCounter)
 | 
					 | 
				
			||||||
            addressCounter++
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        val startColumn = if (iteration == 0 && slice == 0) {
 | 
					 | 
				
			||||||
            2
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            slice * segmentLength
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (column in startColumn until (slice + 1) * segmentLength) {
 | 
					 | 
				
			||||||
            val segmentIndex = column - (slice * segmentLength)
 | 
					 | 
				
			||||||
            //Each address block contains 128 addresses, and we use one per iteration,
 | 
					 | 
				
			||||||
            //so once we do 128 iterations we need to calculate a new address block
 | 
					 | 
				
			||||||
            if (useIndependentAddressing && segmentIndex != 0 && segmentIndex % 128 == 0) {
 | 
					 | 
				
			||||||
                addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock!!, addressCounter)
 | 
					 | 
				
			||||||
                addressCounter++
 | 
					 | 
				
			||||||
                addressBlock.hexColumsPrint(16)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            val previousColumn = if (column == 0) {
 | 
					 | 
				
			||||||
                columnCount - 1
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                column - 1
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            val (l, z) = computeReferenceBlockIndexes(
 | 
					 | 
				
			||||||
                iteration,
 | 
					 | 
				
			||||||
                slice,
 | 
					 | 
				
			||||||
                lane,
 | 
					 | 
				
			||||||
                column,
 | 
					 | 
				
			||||||
                addressBlock
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            matrix[lane][column] =
 | 
					 | 
				
			||||||
                compressionFunctionG(
 | 
					 | 
				
			||||||
                    matrix[lane][previousColumn],
 | 
					 | 
				
			||||||
                    matrix[l][z],
 | 
					 | 
				
			||||||
                    matrix[lane][column],
 | 
					 | 
				
			||||||
                    true
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -23,8 +23,8 @@ package com.ionspin.kotlin.crypto.keyderivation.argon2
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
class Argon2TagTooShort(tagLength: UInt) : RuntimeException("Too short tag (output) requested. Requested: $tagLength")
 | 
					class Argon2TagTooShort(tagLength: UInt) : RuntimeException("Too short tag (output) requested. Requested: $tagLength")
 | 
				
			||||||
class Argon2TagTooLong(tagLength: UInt) : RuntimeException("Too long tag (output) requested. Requested: $tagLength")
 | 
					class Argon2TagTooLong(tagLength: UInt) : RuntimeException("Too long tag (output) requested. Requested: $tagLength")
 | 
				
			||||||
class Argon2TimeTooShort(iterations: UInt) : RuntimeException("Too short time parameter (Too few iterations). Requested iterations: $iterations")
 | 
					class Argon2TimeTooShort(iterations: Int) : RuntimeException("Too short time parameter (Too few iterations). Requested iterations: $iterations")
 | 
				
			||||||
class Argon2TimeTooLong(iterations: UInt) : RuntimeException("Too long time parameter (Too many iterations). Requested iterations: $iterations")
 | 
					class Argon2TimeTooLong(iterations: Int) : RuntimeException("Too long time parameter (Too many iterations). Requested iterations: $iterations")
 | 
				
			||||||
class Argon2MemoryTooLitlle(requestedMemorySize: UInt) : RuntimeException("Requested memory size must be larger than 8 * parallelism. Requested size: $requestedMemorySize")
 | 
					class Argon2MemoryTooLitlle(requestedMemorySize: UInt) : RuntimeException("Requested memory size must be larger than 8 * parallelism. Requested size: $requestedMemorySize")
 | 
				
			||||||
class Argon2MemoryTooMuch(requestedMemorySize: UInt) : RuntimeException("Requested memory size too large. Requested size: $requestedMemorySize")
 | 
					class Argon2MemoryTooMuch(requestedMemorySize: UInt) : RuntimeException("Requested memory size too large. Requested size: $requestedMemorySize")
 | 
				
			||||||
class Argon2LanesTooFew(parallelism: Int) : RuntimeException("Too few, or invalid number of threads requested $parallelism")
 | 
					class Argon2LanesTooFew(parallelism: Int) : RuntimeException("Too few, or invalid number of threads requested $parallelism")
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,405 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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", "EXPERIMENTAL_UNSIGNED_LITERALS")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package com.ionspin.kotlin.crypto.keyderivation.argon2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.bignum.integer.toBigInteger
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.Blake2bPureStateless
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.SRNG
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.argonBlake2bArbitraryLenghtHash
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.compressionFunctionG
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.validateArgonParameters
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.util.*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 16-May-2020
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class ArgonType(val typeId: Int) {
 | 
				
			||||||
 | 
					    Argon2d(0), Argon2i(1), Argon2id(2)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					data class SegmentPosition(
 | 
				
			||||||
 | 
					    val iteration: Int,
 | 
				
			||||||
 | 
					    val lane: Int,
 | 
				
			||||||
 | 
					    val slice: Int
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					data class ArgonResult(
 | 
				
			||||||
 | 
					    val hashBytes: UByteArray,
 | 
				
			||||||
 | 
					    val salt: UByteArray
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    val hashString by lazy { hashBytes.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "") }
 | 
				
			||||||
 | 
					    val saltString by lazy { salt.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "") }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Argon2Pure(
 | 
				
			||||||
 | 
					    private val password: UByteArray,
 | 
				
			||||||
 | 
					    private val salt: UByteArray = ubyteArrayOf(),
 | 
				
			||||||
 | 
					    private val parallelism: Int = 1,
 | 
				
			||||||
 | 
					    private val tagLength: UInt = 64U,
 | 
				
			||||||
 | 
					    requestedMemorySize: UInt = 0U,
 | 
				
			||||||
 | 
					    private val numberOfIterations: Int = 1,
 | 
				
			||||||
 | 
					    private val key: UByteArray = ubyteArrayOf(),
 | 
				
			||||||
 | 
					    private val associatedData: UByteArray = ubyteArrayOf(),
 | 
				
			||||||
 | 
					    private val argonType: ArgonType = ArgonType.Argon2id
 | 
				
			||||||
 | 
					) : Argon2 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    companion object {
 | 
				
			||||||
 | 
					        fun derive(
 | 
				
			||||||
 | 
					            password: String,
 | 
				
			||||||
 | 
					            salt: String? = null,
 | 
				
			||||||
 | 
					            key: String,
 | 
				
			||||||
 | 
					            associatedData: String,
 | 
				
			||||||
 | 
					            parallelism: Int = 16,
 | 
				
			||||||
 | 
					            tagLength: Int = 64,
 | 
				
			||||||
 | 
					            memory: Int = 4096,
 | 
				
			||||||
 | 
					            numberOfIterations: Int = 10,
 | 
				
			||||||
 | 
					        ): ArgonResult {
 | 
				
			||||||
 | 
					            val salt = SRNG.getRandomBytes(64)
 | 
				
			||||||
 | 
					            val argon = Argon2Pure(
 | 
				
			||||||
 | 
					                password.encodeToByteArray().toUByteArray(),
 | 
				
			||||||
 | 
					                salt,
 | 
				
			||||||
 | 
					                parallelism,
 | 
				
			||||||
 | 
					                tagLength.toUInt(),
 | 
				
			||||||
 | 
					                memory.toUInt(),
 | 
				
			||||||
 | 
					                numberOfIterations,
 | 
				
			||||||
 | 
					                key.encodeToByteArray().toUByteArray(),
 | 
				
			||||||
 | 
					                associatedData.encodeToByteArray().toUByteArray(),
 | 
				
			||||||
 | 
					                ArgonType.Argon2id
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            val resultArray = argon.derive()
 | 
				
			||||||
 | 
					            return ArgonResult(resultArray, salt)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor(
 | 
				
			||||||
 | 
					        password: String,
 | 
				
			||||||
 | 
					        salt: String = "",
 | 
				
			||||||
 | 
					        parallelism: Int = 1,
 | 
				
			||||||
 | 
					        tagLength: UInt = 64U,
 | 
				
			||||||
 | 
					        requestedMemorySize: UInt = 0U,
 | 
				
			||||||
 | 
					        numberOfIterations: Int = 10,
 | 
				
			||||||
 | 
					        key: String = "",
 | 
				
			||||||
 | 
					        associatedData: String = "",
 | 
				
			||||||
 | 
					        argonType: ArgonType = ArgonType.Argon2id
 | 
				
			||||||
 | 
					    ) : this(
 | 
				
			||||||
 | 
					        password.encodeToByteArray().toUByteArray(),
 | 
				
			||||||
 | 
					        salt.encodeToByteArray().toUByteArray(),
 | 
				
			||||||
 | 
					        parallelism,
 | 
				
			||||||
 | 
					        tagLength,
 | 
				
			||||||
 | 
					        requestedMemorySize,
 | 
				
			||||||
 | 
					        numberOfIterations,
 | 
				
			||||||
 | 
					        key.encodeToByteArray().toUByteArray(),
 | 
				
			||||||
 | 
					        associatedData.encodeToByteArray().toUByteArray(),
 | 
				
			||||||
 | 
					        argonType
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //We support only the latest version
 | 
				
			||||||
 | 
					    private val versionNumber: UInt = 0x13U
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Use either requested memory size, or default, or throw exception if the requested amount is less than 8*parallelism
 | 
				
			||||||
 | 
					    private val memorySize = if (requestedMemorySize == 0U) {
 | 
				
			||||||
 | 
					        ((8 * parallelism) * 2).toUInt()
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        requestedMemorySize
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    private val blockCount = (memorySize / (4U * parallelism.toUInt())) * (4U * parallelism.toUInt())
 | 
				
			||||||
 | 
					    private val columnCount = (blockCount / parallelism.toUInt()).toInt()
 | 
				
			||||||
 | 
					    private val segmentLength = columnCount / 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val useIndependentAddressing = argonType == ArgonType.Argon2id || argonType == ArgonType.Argon2i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // State
 | 
				
			||||||
 | 
					    private val matrix: ArgonMatrix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    init {
 | 
				
			||||||
 | 
					        matrix = ArgonMatrix(columnCount, parallelism)
 | 
				
			||||||
 | 
					        validateArgonParameters(
 | 
				
			||||||
 | 
					            password,
 | 
				
			||||||
 | 
					            salt,
 | 
				
			||||||
 | 
					            parallelism,
 | 
				
			||||||
 | 
					            tagLength,
 | 
				
			||||||
 | 
					            requestedMemorySize,
 | 
				
			||||||
 | 
					            numberOfIterations,
 | 
				
			||||||
 | 
					            key,
 | 
				
			||||||
 | 
					            associatedData,
 | 
				
			||||||
 | 
					            argonType
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun populateAddressBlock(
 | 
				
			||||||
 | 
					        iteration: Int,
 | 
				
			||||||
 | 
					        slice: Int,
 | 
				
			||||||
 | 
					        lane: Int,
 | 
				
			||||||
 | 
					        addressBlock: ArgonBlockPointer,
 | 
				
			||||||
 | 
					        addressCounter: ULong
 | 
				
			||||||
 | 
					    ): ArgonBlockPointer {
 | 
				
			||||||
 | 
					        //Calculate first pass
 | 
				
			||||||
 | 
					        val zeroesBlock = ArgonBlock()
 | 
				
			||||||
 | 
					        val firstPass = compressionFunctionG(
 | 
				
			||||||
 | 
					            zeroesBlock.getBlockPointer(),
 | 
				
			||||||
 | 
					            ArgonBlock(iteration.toULong().toLittleEndianUByteArray() +
 | 
				
			||||||
 | 
					                    lane.toULong().toLittleEndianUByteArray() +
 | 
				
			||||||
 | 
					                    slice.toULong().toLittleEndianUByteArray() +
 | 
				
			||||||
 | 
					                    blockCount.toULong().toLittleEndianUByteArray() +
 | 
				
			||||||
 | 
					                    numberOfIterations.toULong().toLittleEndianUByteArray() +
 | 
				
			||||||
 | 
					                    argonType.typeId.toULong().toLittleEndianUByteArray() +
 | 
				
			||||||
 | 
					                    addressCounter.toLittleEndianUByteArray() +
 | 
				
			||||||
 | 
					                    UByteArray(968) { 0U }
 | 
				
			||||||
 | 
					            ).getBlockPointer(),
 | 
				
			||||||
 | 
					            addressBlock,
 | 
				
			||||||
 | 
					            false
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        val secondPass = compressionFunctionG(
 | 
				
			||||||
 | 
					            zeroesBlock.getBlockPointer(),
 | 
				
			||||||
 | 
					            firstPass,
 | 
				
			||||||
 | 
					            firstPass,
 | 
				
			||||||
 | 
					            false
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return secondPass
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun computeReferenceBlockIndexes(
 | 
				
			||||||
 | 
					        iteration: Int,
 | 
				
			||||||
 | 
					        slice: Int,
 | 
				
			||||||
 | 
					        lane: Int,
 | 
				
			||||||
 | 
					        column: Int,
 | 
				
			||||||
 | 
					        addressBlockPointer: ArgonBlockPointer?
 | 
				
			||||||
 | 
					    ): Pair<Int, Int> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val segmentIndex = (column % segmentLength)
 | 
				
			||||||
 | 
					        val independentIndex = segmentIndex % 128 // 128 is the number of addresses in address block
 | 
				
			||||||
 | 
					        val (j1, j2) = when (argonType) {
 | 
				
			||||||
 | 
					            ArgonType.Argon2d -> {
 | 
				
			||||||
 | 
					                val previousBlockStart = if (column == 0) {
 | 
				
			||||||
 | 
					                    matrix.getBlockPointer(lane, columnCount - 1) //Get last block in the SAME lane
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    matrix.getBlockPointer(lane, column - 1)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                val first32Bit = matrix.sliceArray(previousBlockStart.asInt() until previousBlockStart.asInt() + 4).fromLittleEndianArrayToUInt()
 | 
				
			||||||
 | 
					                val second32Bit = matrix.sliceArray(previousBlockStart.asInt() + 4 until previousBlockStart.asInt() + 8).fromLittleEndianArrayToUInt()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Pair(first32Bit, second32Bit)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ArgonType.Argon2i -> {
 | 
				
			||||||
 | 
					                val first32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8)
 | 
				
			||||||
 | 
					                val second32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8 + 4)
 | 
				
			||||||
 | 
					                Pair(first32Bit, second32Bit)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ArgonType.Argon2id -> {
 | 
				
			||||||
 | 
					                if (iteration == 0 && (slice == 0 || slice == 1)) {
 | 
				
			||||||
 | 
					                    val first32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8)
 | 
				
			||||||
 | 
					                    val second32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8 + 4)
 | 
				
			||||||
 | 
					                    Pair(first32Bit, second32Bit)
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    val previousBlockStart = if (column == 0) {
 | 
				
			||||||
 | 
					                        matrix.getBlockPointer(lane, columnCount - 1) //Get last block in the SAME lane
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        matrix.getBlockPointer(lane, column - 1)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    val first32Bit = matrix.sliceArray(previousBlockStart.asInt() until previousBlockStart.asInt() + 4).fromLittleEndianArrayToUInt()
 | 
				
			||||||
 | 
					                    val second32Bit = matrix.sliceArray(previousBlockStart.asInt() + 4 until previousBlockStart.asInt() + 8).fromLittleEndianArrayToUInt()
 | 
				
			||||||
 | 
					                    Pair(first32Bit, second32Bit)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //If this is first iteration and first slice, block is taken from the current lane
 | 
				
			||||||
 | 
					        val l = if (iteration == 0 && slice == 0) {
 | 
				
			||||||
 | 
					            lane
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            (j2.toBigInteger() % parallelism).intValue()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val referenceAreaSize = if (iteration == 0) {
 | 
				
			||||||
 | 
					            if (slice == 0) {
 | 
				
			||||||
 | 
					                //All indices except the previous
 | 
				
			||||||
 | 
					                segmentIndex - 1
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                if (lane == l) {
 | 
				
			||||||
 | 
					                    //Same lane
 | 
				
			||||||
 | 
					                    column - 1
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    slice * (columnCount / 4) + if (segmentIndex == 0) { // Check if column is first block of the SEGMENT
 | 
				
			||||||
 | 
					                        -1
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        0
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if (lane == l) {
 | 
				
			||||||
 | 
					                columnCount - (columnCount / 4) + (segmentIndex - 1)
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                columnCount - (columnCount / 4) + if (segmentIndex == 0) {
 | 
				
			||||||
 | 
					                    -1
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    0
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val x = (j1.toULong() * j1) shr 32
 | 
				
			||||||
 | 
					        val y = (referenceAreaSize.toULong() * x) shr 32
 | 
				
			||||||
 | 
					        val z = referenceAreaSize.toULong() - 1U - y
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val startPosition = if (iteration == 0) {
 | 
				
			||||||
 | 
					            0
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if (slice == 3) {
 | 
				
			||||||
 | 
					                0
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                (slice + 1) * segmentLength
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        val absolutePosition = (startPosition + z.toInt()) % columnCount
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Pair(l, absolutePosition)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun derive(): UByteArray {
 | 
				
			||||||
 | 
					        val blakeInput = parallelism.toUInt().toLittleEndianUByteArray() +
 | 
				
			||||||
 | 
					                tagLength.toLittleEndianUByteArray() +
 | 
				
			||||||
 | 
					                memorySize.toLittleEndianUByteArray() +
 | 
				
			||||||
 | 
					                numberOfIterations.toUInt().toLittleEndianUByteArray() +
 | 
				
			||||||
 | 
					                versionNumber.toLittleEndianUByteArray() +
 | 
				
			||||||
 | 
					                argonType.typeId.toUInt().toLittleEndianUByteArray() +
 | 
				
			||||||
 | 
					                password.size.toUInt().toLittleEndianUByteArray() + password +
 | 
				
			||||||
 | 
					                salt.size.toUInt().toLittleEndianUByteArray() + salt +
 | 
				
			||||||
 | 
					                key.size.toUInt().toLittleEndianUByteArray() + key +
 | 
				
			||||||
 | 
					                associatedData.size.toUInt().toLittleEndianUByteArray() + associatedData
 | 
				
			||||||
 | 
					        val h0 = Blake2bPureStateless.digest(
 | 
				
			||||||
 | 
					            blakeInput
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //Compute B[i][0]
 | 
				
			||||||
 | 
					        for (i in 0 until parallelism) {
 | 
				
			||||||
 | 
					            matrix.setBlockAt(i, 0,
 | 
				
			||||||
 | 
					                argonBlake2bArbitraryLenghtHash(
 | 
				
			||||||
 | 
					                    (h0 + 0.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray()).toUByteArray(),
 | 
				
			||||||
 | 
					                    1024U
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //Compute B[i][1]
 | 
				
			||||||
 | 
					        for (i in 0 until parallelism) {
 | 
				
			||||||
 | 
					            matrix.setBlockAt(i, 1,
 | 
				
			||||||
 | 
					                argonBlake2bArbitraryLenghtHash(
 | 
				
			||||||
 | 
					                    (h0 + 1.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray()).toUByteArray(),
 | 
				
			||||||
 | 
					                    1024U
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        //Run all iterations over all lanes and all segments
 | 
				
			||||||
 | 
					        executeArgonWithSingleThread()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val acc = ArgonBlock(matrix.getBlockAt(0, columnCount - 1))
 | 
				
			||||||
 | 
					        val accPointer = acc.getBlockPointer()
 | 
				
			||||||
 | 
					        for (i in 1 until parallelism) {
 | 
				
			||||||
 | 
					            accPointer.xorInplaceWith(matrix.getBlockPointer(i, columnCount - 1))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        //Hash the xored last blocks
 | 
				
			||||||
 | 
					        val hash = argonBlake2bArbitraryLenghtHash(acc.storage, tagLength)
 | 
				
			||||||
 | 
					        matrix.clearMatrix()
 | 
				
			||||||
 | 
					        return hash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun executeArgonWithSingleThread() {
 | 
				
			||||||
 | 
					        for (iteration in 0 until numberOfIterations) {
 | 
				
			||||||
 | 
					            for (slice in 0 until 4) {
 | 
				
			||||||
 | 
					                for (lane in 0 until parallelism) {
 | 
				
			||||||
 | 
					                    val segmentPosition = SegmentPosition(iteration, lane, slice)
 | 
				
			||||||
 | 
					                    processSegment(segmentPosition)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun processSegment(segmentPosition: SegmentPosition) {
 | 
				
			||||||
 | 
					        val iteration = segmentPosition.iteration
 | 
				
			||||||
 | 
					        val slice = segmentPosition.slice
 | 
				
			||||||
 | 
					        val lane = segmentPosition.lane
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var addressBlock: ArgonBlockPointer? = null
 | 
				
			||||||
 | 
					        var addressCounter = 1UL //Starts from 1 in each segment as defined by the spec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //Generate initial segment address block
 | 
				
			||||||
 | 
					        if (useIndependentAddressing) {
 | 
				
			||||||
 | 
					            addressBlock = ArgonBlock().getBlockPointer()
 | 
				
			||||||
 | 
					            addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock, addressCounter)
 | 
				
			||||||
 | 
					            addressCounter++
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        val startColumn = if (iteration == 0 && slice == 0) {
 | 
				
			||||||
 | 
					            2
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            slice * segmentLength
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (column in startColumn until (slice + 1) * segmentLength) {
 | 
				
			||||||
 | 
					            val segmentIndex = column - (slice * segmentLength)
 | 
				
			||||||
 | 
					            //Each address block contains 128 addresses, and we use one per iteration,
 | 
				
			||||||
 | 
					            //so once we do 128 iterations we need to calculate a new address block
 | 
				
			||||||
 | 
					            if (useIndependentAddressing && segmentIndex != 0 && segmentIndex % 128 == 0) {
 | 
				
			||||||
 | 
					                addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock!!, addressCounter)
 | 
				
			||||||
 | 
					                addressCounter++
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            val previousColumn = if (column == 0) {
 | 
				
			||||||
 | 
					                columnCount - 1
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                column - 1
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            val (l, z) = computeReferenceBlockIndexes(
 | 
				
			||||||
 | 
					                iteration,
 | 
				
			||||||
 | 
					                slice,
 | 
				
			||||||
 | 
					                lane,
 | 
				
			||||||
 | 
					                column,
 | 
				
			||||||
 | 
					                addressBlock
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            matrix.setBlockAt(lane, column,
 | 
				
			||||||
 | 
					                compressionFunctionG(
 | 
				
			||||||
 | 
					                    matrix.getBlockPointer(lane, previousColumn),
 | 
				
			||||||
 | 
					                    matrix.getBlockPointer(l,z),
 | 
				
			||||||
 | 
					                    matrix.getBlockPointer(lane,column),
 | 
				
			||||||
 | 
					                    true
 | 
				
			||||||
 | 
					                ).getAsUByteArray()
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -18,8 +18,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.ionspin.kotlin.crypto.keyderivation.argon2
 | 
					package com.ionspin.kotlin.crypto.keyderivation.argon2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b
 | 
					import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bPure
 | 
				
			||||||
import com.ionspin.kotlin.crypto.util.*
 | 
					import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.BLOCK_SIZE
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.util.plus
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.util.rotateRight
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Created by Ugljesa Jovanovic
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
@ -27,28 +29,28 @@ import com.ionspin.kotlin.crypto.util.*
 | 
				
			|||||||
 * on 16-May-2020
 | 
					 * on 16-May-2020
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
object Argon2Utils {
 | 
					object Argon2Utils {
 | 
				
			||||||
 | 
					    const val BLOCK_SIZE = 1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const val R1 = 32
 | 
					    const val R1 = 32
 | 
				
			||||||
    const val R2 = 24
 | 
					    const val R2 = 24
 | 
				
			||||||
    const val R3 = 16
 | 
					    const val R3 = 16
 | 
				
			||||||
    const val R4 = 63
 | 
					    const val R4 = 63
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //based on Blake2b mixRound
 | 
					    //Based on Blake2b mix
 | 
				
			||||||
    private fun mixRound(input: Array<UByte>): Array<ULong> {
 | 
					    internal fun inplaceMixRound(v : ULongArray) : ULongArray{
 | 
				
			||||||
        var v = input.chunked(8).map { it.fromLittleEndianArrayToULong() }.toTypedArray()
 | 
					        mix(v, 0, 4, 8, 12)
 | 
				
			||||||
        v = mix(v, 0, 4, 8, 12)
 | 
					        mix(v, 1, 5, 9, 13)
 | 
				
			||||||
        v = mix(v, 1, 5, 9, 13)
 | 
					        mix(v, 2, 6, 10, 14)
 | 
				
			||||||
        v = mix(v, 2, 6, 10, 14)
 | 
					        mix(v, 3, 7, 11, 15)
 | 
				
			||||||
        v = mix(v, 3, 7, 11, 15)
 | 
					        mix(v, 0, 5, 10, 15)
 | 
				
			||||||
        v = mix(v, 0, 5, 10, 15)
 | 
					        mix(v, 1, 6, 11, 12)
 | 
				
			||||||
        v = mix(v, 1, 6, 11, 12)
 | 
					        mix(v, 2, 7, 8, 13)
 | 
				
			||||||
        v = mix(v, 2, 7, 8, 13)
 | 
					        mix(v, 3, 4, 9, 14)
 | 
				
			||||||
        v = mix(v, 3, 4, 9, 14)
 | 
					        return v //Just for chaining, array is mixed in place
 | 
				
			||||||
        return v
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Based on Blake2b mix
 | 
					    //Based on Blake2b mix
 | 
				
			||||||
    private fun mix(v: Array<ULong>, a: Int, b: Int, c: Int, d: Int): Array<ULong> {
 | 
					    private fun mix(v: ULongArray, a: Int, b: Int, c: Int, d: Int) {
 | 
				
			||||||
        v[a] = (v[a] + v[b] + 2U * (v[a] and 0xFFFFFFFFUL) * (v[b] and 0xFFFFFFFFUL))
 | 
					        v[a] = (v[a] + v[b] + 2U * (v[a] and 0xFFFFFFFFUL) * (v[b] and 0xFFFFFFFFUL))
 | 
				
			||||||
        v[d] = (v[d] xor v[a]) rotateRight R1
 | 
					        v[d] = (v[d] xor v[a]) rotateRight R1
 | 
				
			||||||
        v[c] = (v[c] + v[d] + 2U * (v[c] and 0xFFFFFFFFUL) * (v[d] and 0xFFFFFFFFUL))
 | 
					        v[c] = (v[c] + v[d] + 2U * (v[c] and 0xFFFFFFFFUL) * (v[d] and 0xFFFFFFFFUL))
 | 
				
			||||||
@ -57,11 +59,10 @@ object Argon2Utils {
 | 
				
			|||||||
        v[d] = (v[d] xor v[a]) rotateRight R3
 | 
					        v[d] = (v[d] xor v[a]) rotateRight R3
 | 
				
			||||||
        v[c] = (v[c] + v[d] + 2U * (v[c] and 0xFFFFFFFFUL) * (v[d] and 0xFFFFFFFFUL))
 | 
					        v[c] = (v[c] + v[d] + 2U * (v[c] and 0xFFFFFFFFUL) * (v[d] and 0xFFFFFFFFUL))
 | 
				
			||||||
        v[b] = (v[b] xor v[c]) rotateRight R4
 | 
					        v[b] = (v[b] xor v[c]) rotateRight R4
 | 
				
			||||||
        return v
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun extractColumnFromGBlock(gBlock: Array<UByte>, columnPosition: Int): Array<UByte> {
 | 
					    internal fun extractColumnFromGBlock(gBlock: UByteArray, columnPosition: Int): UByteArray {
 | 
				
			||||||
        val result = Array<UByte>(128) { 0U }
 | 
					        val result = UByteArray(128) { 0U }
 | 
				
			||||||
        for (i in 0..7) {
 | 
					        for (i in 0..7) {
 | 
				
			||||||
            gBlock.copyOfRange(i * 128 + (columnPosition * 16), i * 128 + (columnPosition * 16) + 16)
 | 
					            gBlock.copyOfRange(i * 128 + (columnPosition * 16), i * 128 + (columnPosition * 16) + 16)
 | 
				
			||||||
                .copyInto(result, i * 16)
 | 
					                .copyInto(result, i * 16)
 | 
				
			||||||
@ -69,69 +70,50 @@ object Argon2Utils {
 | 
				
			|||||||
        return result
 | 
					        return result
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun copyIntoGBlockColumn(gBlock: Array<UByte>, columnPosition: Int, columnData: Array<UByte>) {
 | 
					
 | 
				
			||||||
        for (i in 0..7) {
 | 
					 | 
				
			||||||
            val column = columnData.copyOfRange(i * 16, i * 16 + 16)
 | 
					 | 
				
			||||||
            column.copyInto(gBlock, i * 128 + columnPosition * 16)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    internal fun compressionFunctionG(
 | 
					    internal fun compressionFunctionG(
 | 
				
			||||||
        previousBlock: Array<UByte>,
 | 
					        previousBlock: ArgonBlockPointer,
 | 
				
			||||||
        referenceBlock: Array<UByte>,
 | 
					        referenceBlock: ArgonBlockPointer,
 | 
				
			||||||
        currentBlock: Array<UByte>,
 | 
					        currentBlock: ArgonBlockPointer,
 | 
				
			||||||
        xorWithCurrentBlock: Boolean
 | 
					        xorWithCurrentBlock: Boolean
 | 
				
			||||||
    ): Array<UByte> {
 | 
					    ): ArgonBlockPointer {
 | 
				
			||||||
        val r = referenceBlock xor previousBlock
 | 
					        val r = (referenceBlock xorBlocksAndGetPointerToNewBlock previousBlock).getBlockPointer()
 | 
				
			||||||
        val q = Array<UByte>(1024) { 0U }
 | 
					        //Since we are doing inplace xors, we don't need the Q that exists in specification
 | 
				
			||||||
        val z = Array<UByte>(1024) { 0U }
 | 
					        val z = ArgonBlock().getBlockPointer()
 | 
				
			||||||
        // Do the argon/blake2b mixing on rows
 | 
					        // Do the argon/blake2b mixing on rows
 | 
				
			||||||
        for (i in 0..7) {
 | 
					        for (i in 0..7) {
 | 
				
			||||||
            val startOfRow = (i * 8 * 16)
 | 
					            z.setRowFromMixedULongs(i, inplaceMixRound(r.getRowOfULongsForMixing(i)))
 | 
				
			||||||
            val endOfRow = startOfRow + (8 * 16)
 | 
					 | 
				
			||||||
            val rowToMix = r.copyOfRange(startOfRow, endOfRow)
 | 
					 | 
				
			||||||
            mixRound(rowToMix)
 | 
					 | 
				
			||||||
                .map { it.toLittleEndianUByteArray() }
 | 
					 | 
				
			||||||
                .flatMap { it.asIterable() }
 | 
					 | 
				
			||||||
                .toTypedArray()
 | 
					 | 
				
			||||||
                .copyInto(q, startOfRow)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // Do the argon/blake2b mixing on columns
 | 
					        // Do the argon/blake2b mixing on columns
 | 
				
			||||||
        for (i in 0..7) {
 | 
					        for (i in 0..7) {
 | 
				
			||||||
            copyIntoGBlockColumn(
 | 
					            z.setColumnFromMixedULongs(i, inplaceMixRound(z.getColumnOfULongsForMixing(i)))
 | 
				
			||||||
                z,
 | 
					 | 
				
			||||||
                i,
 | 
					 | 
				
			||||||
                mixRound(extractColumnFromGBlock(q, i))
 | 
					 | 
				
			||||||
                    .map { it.toLittleEndianUByteArray() }
 | 
					 | 
				
			||||||
                    .flatMap { it.asIterable() }
 | 
					 | 
				
			||||||
                    .toTypedArray()
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        val final = if (xorWithCurrentBlock) {
 | 
					        val final = if (xorWithCurrentBlock) {
 | 
				
			||||||
            (z xor r) xor currentBlock
 | 
					            (z xorInplaceWith r) xorInplaceWith  currentBlock
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            z xor r
 | 
					            z xorInplaceWith r
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return final
 | 
					        return final
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    internal fun argonBlake2bArbitraryLenghtHash(input: Array<UByte>, length: UInt): Array<UByte> {
 | 
					    internal fun argonBlake2bArbitraryLenghtHash(input: UByteArray, length: UInt): UByteArray {
 | 
				
			||||||
        if (length <= 64U) {
 | 
					        if (length <= 64U) {
 | 
				
			||||||
            return Blake2b.digest(inputMessage = length + input, hashLength = length.toInt())
 | 
					            return Blake2bPure.digest(inputMessage = length + input, hashLength = length.toInt())
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        //We can cast to int because UInt even if MAX_VALUE divided by 32 is guaranteed not to overflow
 | 
					        //We can cast to int because UInt even if MAX_VALUE divided by 32 is guaranteed not to overflow
 | 
				
			||||||
        val numberOf64ByteBlocks = (1U + ((length - 1U) / 32U) - 2U).toInt() // equivalent  to ceil(length/32) - 2
 | 
					        val numberOf64ByteBlocks = (1U + ((length - 1U) / 32U) - 2U).toInt() // equivalent  to ceil(length/32) - 2
 | 
				
			||||||
        val v = Array<Array<UByte>>(numberOf64ByteBlocks) { emptyArray() }
 | 
					        val v = Array<UByteArray>(numberOf64ByteBlocks) { ubyteArrayOf() }
 | 
				
			||||||
        v[0] = Blake2b.digest(length + input)
 | 
					        v[0] = Blake2bPure.digest(length + input)
 | 
				
			||||||
        for (i in 1 until numberOf64ByteBlocks) {
 | 
					        for (i in 1 until numberOf64ByteBlocks) {
 | 
				
			||||||
            v[i] = Blake2b.digest(v[i - 1])
 | 
					            v[i] = Blake2bPure.digest(v[i - 1])
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        val remainingPartOfInput = length.toInt() - numberOf64ByteBlocks * 32
 | 
					        val remainingPartOfInput = length.toInt() - numberOf64ByteBlocks * 32
 | 
				
			||||||
        val vLast = Blake2b.digest(v[numberOf64ByteBlocks - 1], hashLength = remainingPartOfInput)
 | 
					        val vLast = Blake2bPure.digest(v[numberOf64ByteBlocks - 1], hashLength = remainingPartOfInput)
 | 
				
			||||||
        val concat =
 | 
					        val concat =
 | 
				
			||||||
            (v.map { it.copyOfRange(0, 32) })
 | 
					            (v.map { it.copyOfRange(0, 32) })
 | 
				
			||||||
                .plus(listOf(vLast))
 | 
					                .plus(listOf(vLast))
 | 
				
			||||||
                .foldRight(emptyArray<UByte>()) { arrayOfUBytes, acc -> arrayOfUBytes + acc }
 | 
					                .foldRight(ubyteArrayOf()) { arrayOfUBytes, acc -> arrayOfUBytes + acc }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return concat
 | 
					        return concat
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -143,14 +125,14 @@ object Argon2Utils {
 | 
				
			|||||||
     * tagLength, requested memory size and number of iterations, so no need to check for upper bound, just lower.
 | 
					     * tagLength, requested memory size and number of iterations, so no need to check for upper bound, just lower.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    internal fun validateArgonParameters(
 | 
					    internal fun validateArgonParameters(
 | 
				
			||||||
        password: Array<UByte>,
 | 
					        password: UByteArray,
 | 
				
			||||||
        salt: Array<UByte>,
 | 
					        salt: UByteArray,
 | 
				
			||||||
        parallelism: Int ,
 | 
					        parallelism: Int ,
 | 
				
			||||||
        tagLength: UInt,
 | 
					        tagLength: UInt,
 | 
				
			||||||
        requestedMemorySize: UInt ,
 | 
					        requestedMemorySize: UInt ,
 | 
				
			||||||
        numberOfIterations: UInt ,
 | 
					        numberOfIterations: Int ,
 | 
				
			||||||
        key: Array<UByte>,
 | 
					        key: UByteArray,
 | 
				
			||||||
        associatedData: Array<UByte>,
 | 
					        associatedData: UByteArray,
 | 
				
			||||||
        argonType: ArgonType
 | 
					        argonType: ArgonType
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -170,9 +152,16 @@ object Argon2Utils {
 | 
				
			|||||||
            throw Argon2MemoryTooLitlle(requestedMemorySize)
 | 
					            throw Argon2MemoryTooLitlle(requestedMemorySize)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        //Number of iterations
 | 
					        //Number of iterations
 | 
				
			||||||
        if (numberOfIterations <= 0U) {
 | 
					        if (numberOfIterations <= 0) {
 | 
				
			||||||
            throw Argon2TimeTooShort(numberOfIterations)
 | 
					            throw Argon2TimeTooShort(numberOfIterations)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ------------ Arithmetic and other utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun UByteArray.xorWithBlock(other : ArgonMatrix, rowPosition: Int, columnPosition: Int) : UByteArray {
 | 
				
			||||||
 | 
					    return UByteArray(BLOCK_SIZE) { this[it] xor other[rowPosition, columnPosition, it] }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,285 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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", "EXPERIMENTAL_UNSIGNED_LITERALS")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package com.ionspin.kotlin.crypto.keyderivation.argon2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.util.xor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Represents a pointer to a Argon2 Block, this abstracts what the backing structure is, a Argon 2 Matrix or
 | 
				
			||||||
 | 
					 * or a UByteArray block
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					interface ArgonBlockPointer {
 | 
				
			||||||
 | 
					    companion object {
 | 
				
			||||||
 | 
					        private val _emitLongArray : LongArray = longArrayOf(1L,2L)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    val blockStartPosition: Int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun pointerArithmetic(block : (Int, Int) -> Int) : ArgonBlockPointer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    infix fun xorBlocksAndGetPointerToNewBlock(other: ArgonBlockPointer) : ArgonBlock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator fun get(blockPosition: Int) : UByte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator fun set(blockPosition: Int, value: UByte)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    infix fun xorInplaceWith(other: ArgonBlockPointer) : ArgonBlockPointer {
 | 
				
			||||||
 | 
					        for (it in 0 until 1024) {
 | 
				
			||||||
 | 
					            this[it] = this[it] xor other[it]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return this //For chaining
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun asInt() : Int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun getAsUByteArray() : UByteArray
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun ArgonBlockPointer._emitLongArray() : LongArray = longArrayOf(0,1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun ArgonBlockPointer.getRowOfULongsForMixing(rowIndex: Int) : ULongArray {
 | 
				
			||||||
 | 
					    // Each row has 16 unsigned longs (16 ulongs * 8 bytes = 128 bytes) -- Argon2 considers this as 2 word unsigned
 | 
				
			||||||
 | 
					    // numbers, so strictly speaking argon representation is 8 * 8 matrix of 2 word unsigned numbers (registers
 | 
				
			||||||
 | 
					    val ulongArray = ULongArray(16)
 | 
				
			||||||
 | 
					    for (columnIndex in 0 until 16) {
 | 
				
			||||||
 | 
					        var ulong = 0UL
 | 
				
			||||||
 | 
					        //Now we create the ulong
 | 
				
			||||||
 | 
					        for (bytePosition in 0 until 8) {
 | 
				
			||||||
 | 
					            ulong = ulong or (this[rowIndex * 128 + columnIndex * 8 + bytePosition].toULong() shl (bytePosition * 8))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        ulongArray[columnIndex] = ulong
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ulongArray
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun ArgonBlockPointer.setRowFromMixedULongs(rowIndex: Int, ulongs: ULongArray) {
 | 
				
			||||||
 | 
					    // Each row has 16 unsigned longs (16 ulongs * 8 bytes = 128 bytes) -- Argon2 considers this as 2 word unsigned
 | 
				
			||||||
 | 
					    // numbers, so strictly speaking argon representation is 8 * 8 matrix of 2 word unsigned numbers (registers
 | 
				
			||||||
 | 
					    for (columnIndex in 0 until 16) {
 | 
				
			||||||
 | 
					        val ulongToConvert = ulongs[columnIndex]
 | 
				
			||||||
 | 
					        for (bytePosition in 0 until 8) {
 | 
				
			||||||
 | 
					            this[rowIndex * 128 + columnIndex * 8 + bytePosition] = ((ulongToConvert shr (bytePosition * 8)) and 0xFFU).toUByte()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun ArgonBlockPointer.getColumnOfULongsForMixing(columnIndex: Int) : ULongArray {
 | 
				
			||||||
 | 
					    //In Argon2 representation there are 8 double word registers (numbers, but we work with 16 single word ulongs
 | 
				
			||||||
 | 
					    val ulongArray = ULongArray(16)
 | 
				
			||||||
 | 
					    //There are 8 rows that consist of 2 words (registers, in our case ulongs) each
 | 
				
			||||||
 | 
					    for (rowIndex in 0 until 8) {
 | 
				
			||||||
 | 
					        var ulong = 0UL
 | 
				
			||||||
 | 
					        //Now we create the ulong
 | 
				
			||||||
 | 
					        for (bytePosition in 0 until 8) {
 | 
				
			||||||
 | 
					            ulong = ulong or (this[rowIndex * 128 + columnIndex * 16 + bytePosition].toULong() shl (bytePosition * 8))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        ulongArray[rowIndex * 2] = ulong
 | 
				
			||||||
 | 
					        ulong = 0UL
 | 
				
			||||||
 | 
					        // But unlike in columns where we can directly iterate and get all TWO WORD registers, here we also need to grab
 | 
				
			||||||
 | 
					        // the next word
 | 
				
			||||||
 | 
					        for (bytePosition in 8 until 16) {
 | 
				
			||||||
 | 
					            ulong = ulong or (this[rowIndex * 128 + columnIndex * 16 + bytePosition].toULong() shl (bytePosition * 8))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        ulongArray[rowIndex * 2 + 1] = ulong
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ulongArray
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun ArgonBlockPointer.setColumnFromMixedULongs(columnIndex: Int, ulongs: ULongArray)  {
 | 
				
			||||||
 | 
					    //In Argon2 representation there are 8 double word registers (numbers, but we work with 16 single word ulongs
 | 
				
			||||||
 | 
					    //There are 8 rows that consist of 2 words (registers, in our case ulongs) each
 | 
				
			||||||
 | 
					    var ulongToConvert = 0UL
 | 
				
			||||||
 | 
					    for (rowIndex in 0 until 8) {
 | 
				
			||||||
 | 
					        ulongToConvert = ulongs[rowIndex * 2]
 | 
				
			||||||
 | 
					        //Now we create the ulong
 | 
				
			||||||
 | 
					        for (bytePosition in 0 until 8) {
 | 
				
			||||||
 | 
					            this[rowIndex * 128 + columnIndex * 16 + bytePosition] = ((ulongToConvert shr (bytePosition * 8)) and 0xFFU).toUByte()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // But unlike in columns where we can directly iterate and get all TWO WORD registers, here we also need to set
 | 
				
			||||||
 | 
					        // the next word
 | 
				
			||||||
 | 
					        ulongToConvert = ulongs[rowIndex * 2 + 1]
 | 
				
			||||||
 | 
					        for (bytePosition in 8 until 16) {
 | 
				
			||||||
 | 
					            this[rowIndex * 128 + columnIndex * 16 + bytePosition] = ((ulongToConvert shr (bytePosition * 8)) and 0xFFU).toUByte()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun ArgonBlockPointer.getUIntFromPosition(positionInBlock: Int) : UInt {
 | 
				
			||||||
 | 
					    var uint = 0U
 | 
				
			||||||
 | 
					    for (i in 0 until 4) {
 | 
				
			||||||
 | 
					        uint = uint or (this[positionInBlock + i].toUInt() shl (i * 8))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return uint
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 21-May-2020
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					 class ArgonMatrix(val columnCount: Int, val rowCount: Int) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internal val storage: UByteArray = UByteArray(columnCount * rowCount * 1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator fun get(rowPosition: Int, columnPosition: Int, inBlockPosition: Int) : UByte {
 | 
				
			||||||
 | 
					        if (rowPosition > rowCount - 1) {
 | 
				
			||||||
 | 
					            throw RuntimeException("Invalid row (lane) requested: $rowPosition, rowCount: $rowCount")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (columnPosition > columnCount - 1) {
 | 
				
			||||||
 | 
					            throw RuntimeException("Invalid column requested: $columnPosition, columnCount: $columnCount")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return storage[getBlockStartPositionPointer(rowPosition, columnPosition) + inBlockPosition]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val size = storage.size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator fun get(absolutePosition: Int) : UByte {
 | 
				
			||||||
 | 
					        return storage[absolutePosition]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator fun set(rowPosition: Int, columnPosition: Int, inBlockPosition: Int, value: UByte) {
 | 
				
			||||||
 | 
					        storage[getBlockStartPositionPointer(rowPosition, columnPosition) + inBlockPosition] = value
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator fun set(absolutePosition: Int, value: UByte) {
 | 
				
			||||||
 | 
					        storage[absolutePosition] = value
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun getBlockPointer(rowPosition: Int, columnPosition: Int) : ArgonBlockPointer {
 | 
				
			||||||
 | 
					        return ArgonBlockPointerWithMatrix(getBlockStartPositionPointer(rowPosition, columnPosition), this)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun sliceArray(indices: IntRange): UByteArray {
 | 
				
			||||||
 | 
					        return storage.sliceArray(indices)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun getBlockAt(rowPosition: Int, columnPosition: Int) : UByteArray {
 | 
				
			||||||
 | 
					                println("Expensive get")
 | 
				
			||||||
 | 
					        return storage.copyOfRange(
 | 
				
			||||||
 | 
					            getBlockStartPositionPointer(rowPosition, columnPosition),
 | 
				
			||||||
 | 
					            getBlockStartPositionPointer(rowPosition, columnPosition) + 1024
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun setBlockAt(rowPosition: Int, columnPosition: Int, blockValue: UByteArray) {
 | 
				
			||||||
 | 
					        blockValue.copyInto(
 | 
				
			||||||
 | 
					            storage,
 | 
				
			||||||
 | 
					            getBlockStartPositionPointer(rowPosition, columnPosition)
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private inline fun getBlockStartPositionPointer(rowPosition: Int, columnPosition: Int) : Int {
 | 
				
			||||||
 | 
					        return rowPosition * columnCount * 1024 + columnPosition * 1024
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internal fun clearMatrix() {
 | 
				
			||||||
 | 
					        for( index in storage.indices) { storage[index] = 0U }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private class ArgonBlockPointerWithMatrix constructor(override val blockStartPosition: Int, val matrix: ArgonMatrix) : ArgonBlockPointer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override fun pointerArithmetic(block: (Int, Int) -> Int): ArgonBlockPointer {
 | 
				
			||||||
 | 
					            return ArgonBlockPointerWithMatrix(block(blockStartPosition, matrix.size), matrix)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override fun asInt(): Int {
 | 
				
			||||||
 | 
					            return blockStartPosition
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override operator fun get(blockPosition: Int) : UByte {
 | 
				
			||||||
 | 
					            return matrix[blockStartPosition + blockPosition]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override fun set(blockPosition: Int, value: UByte) {
 | 
				
			||||||
 | 
					            matrix[blockStartPosition + blockPosition] = value
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override infix fun xorBlocksAndGetPointerToNewBlock(other: ArgonBlockPointer) : ArgonBlock {
 | 
				
			||||||
 | 
					            return ArgonBlock(UByteArray(1024){
 | 
				
			||||||
 | 
					                matrix[blockStartPosition + it] xor other[it]
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override fun getAsUByteArray(): UByteArray {
 | 
				
			||||||
 | 
					            return matrix.storage.slice(blockStartPosition until blockStartPosition + 1024).toUByteArray()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Suppress("NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS")
 | 
				
			||||||
 | 
					inline class ArgonBlock internal constructor(internal val storage: UByteArray) {
 | 
				
			||||||
 | 
					    constructor() : this(UByteArray(1024))
 | 
				
			||||||
 | 
					    operator fun get(index: Int) : UByte {
 | 
				
			||||||
 | 
					        return storage.get(index)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    operator fun set(index: Int, value: UByte) {
 | 
				
			||||||
 | 
					        storage.set(index, value)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val size: Int get() = storage.size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internal fun getAsUByteArray() : UByteArray = storage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun getBlockPointer() : ArgonBlockPointer{
 | 
				
			||||||
 | 
					        return ArgonBlockPointerWithBlock( this)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    infix fun xorInplaceWith(other: ArgonBlock) : ArgonBlock {
 | 
				
			||||||
 | 
					        storage.indices.forEach {
 | 
				
			||||||
 | 
					            this[it] = this[it] xor other[it]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return this //For chaining
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private class ArgonBlockPointerWithBlock constructor(val storageBlock: ArgonBlock) : ArgonBlockPointer {
 | 
				
			||||||
 | 
					        override val blockStartPosition: Int = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override fun pointerArithmetic(block: (Int, Int) -> Int): ArgonBlockPointer {
 | 
				
			||||||
 | 
					            throw RuntimeException("Haven't really tought out pointer arithmetic with blocks")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override fun asInt(): Int {
 | 
				
			||||||
 | 
					            return blockStartPosition
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        override operator fun get(blockPosition: Int) : UByte {
 | 
				
			||||||
 | 
					            return storageBlock[blockPosition]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override fun set(blockPosition: Int, value: UByte) {
 | 
				
			||||||
 | 
					            storageBlock[blockPosition] = value
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override infix fun xorBlocksAndGetPointerToNewBlock(other: ArgonBlockPointer) : ArgonBlock {
 | 
				
			||||||
 | 
					            return ArgonBlock(UByteArray(1024){
 | 
				
			||||||
 | 
					                storageBlock[it] xor other[it]
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        override fun getAsUByteArray(): UByteArray {
 | 
				
			||||||
 | 
					            return storageBlock.storage
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,241 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *    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.symmetric
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.SRNG
 | 
				
			||||||
 | 
					import com.ionspin.kotlin.crypto.util.xor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Advanced encryption standard with cipher block chaining and PKCS #5
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * For bulk encryption/decryption use [AesCbcPure.encrypt] and [AesCbcPure.decrypt]
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * To get an instance of AesCbc and then feed it data sequentially with [addData] use [createEncryptor] and [createDecryptor]
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Created by Ugljesa Jovanovic
 | 
				
			||||||
 | 
					 * ugljesa.jovanovic@ionspin.com
 | 
				
			||||||
 | 
					 * on 21-Sep-2019
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AesCbcPure internal constructor(val aesKey: AesKey, val mode: Mode, initializationVector: UByteArray? = null) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    companion object {
 | 
				
			||||||
 | 
					        const val BLOCK_BYTES = 16
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all
 | 
				
			||||||
 | 
					         * data call [encrypt]
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        fun createEncryptor(aesKey: AesKey) : AesCbcPure {
 | 
				
			||||||
 | 
					            return AesCbcPure(aesKey, Mode.ENCRYPT)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all
 | 
				
			||||||
 | 
					         * data call [decrypt]
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        fun createDecryptor(aesKey : AesKey) : AesCbcPure {
 | 
				
			||||||
 | 
					            return AesCbcPure(aesKey, Mode.DECRYPT)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Bulk encryption, returns encrypted data and a random initialization vector
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        fun encrypt(aesKey: AesKey, data: UByteArray): EncryptedDataAndInitializationVector {
 | 
				
			||||||
 | 
					            val aesCbc = AesCbcPure(aesKey, Mode.ENCRYPT)
 | 
				
			||||||
 | 
					            aesCbc.addData(data)
 | 
				
			||||||
 | 
					            return aesCbc.encrypt()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Bulk decryption, returns decrypted data
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        fun decrypt(aesKey: AesKey, data: UByteArray, initialCounter: UByteArray? = null): UByteArray {
 | 
				
			||||||
 | 
					            val aesCbc = AesCbcPure(aesKey, Mode.DECRYPT, initialCounter)
 | 
				
			||||||
 | 
					            aesCbc.addData(data)
 | 
				
			||||||
 | 
					            return aesCbc.decrypt()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private fun padToBlock(unpadded: UByteArray): UByteArray {
 | 
				
			||||||
 | 
					            val paddingSize = 16 - unpadded.size
 | 
				
			||||||
 | 
					            if (unpadded.size == BLOCK_BYTES) {
 | 
				
			||||||
 | 
					                return unpadded
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (unpadded.size == BLOCK_BYTES) {
 | 
				
			||||||
 | 
					                return UByteArray(BLOCK_BYTES) {
 | 
				
			||||||
 | 
					                    BLOCK_BYTES.toUByte()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (unpadded.size > BLOCK_BYTES) {
 | 
				
			||||||
 | 
					                throw IllegalStateException("Block larger than 128 bytes")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return UByteArray(BLOCK_BYTES) {
 | 
				
			||||||
 | 
					                when (it) {
 | 
				
			||||||
 | 
					                    in unpadded.indices -> unpadded[it]
 | 
				
			||||||
 | 
					                    else -> paddingSize.toUByte()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var currentOutput: UByteArray = ubyteArrayOf()
 | 
				
			||||||
 | 
					    var previousEncrypted: UByteArray = ubyteArrayOf()
 | 
				
			||||||
 | 
					    val initVector = if (initializationVector.isNullOrEmpty()) {
 | 
				
			||||||
 | 
					        SRNG.getRandomBytes(16)
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        initializationVector
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val output = MutableList<UByteArray>(0) { ubyteArrayOf() }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var buffer: UByteArray = UByteArray(16) { 0U }
 | 
				
			||||||
 | 
					    var bufferCounter = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun addData(data: UByteArray) {
 | 
				
			||||||
 | 
					        //Padding
 | 
				
			||||||
 | 
					        when {
 | 
				
			||||||
 | 
					            bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
 | 
				
			||||||
 | 
					            bufferCounter + data.size >= BLOCK_BYTES -> {
 | 
				
			||||||
 | 
					                val chunked = data.chunked(BLOCK_BYTES)
 | 
				
			||||||
 | 
					                chunked.forEach { chunk ->
 | 
				
			||||||
 | 
					                    if (bufferCounter + chunk.size < BLOCK_BYTES) {
 | 
				
			||||||
 | 
					                        appendToBuffer(chunk.toUByteArray(), bufferCounter)
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        chunk.toUByteArray().copyInto(
 | 
				
			||||||
 | 
					                            destination = buffer,
 | 
				
			||||||
 | 
					                            destinationOffset = bufferCounter,
 | 
				
			||||||
 | 
					                            startIndex = 0,
 | 
				
			||||||
 | 
					                            endIndex = BLOCK_BYTES - bufferCounter
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                        output += consumeBlock(buffer)
 | 
				
			||||||
 | 
					                        buffer = UByteArray(BLOCK_BYTES) {
 | 
				
			||||||
 | 
					                            when (it) {
 | 
				
			||||||
 | 
					                                in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> {
 | 
				
			||||||
 | 
					                                    chunk[it + (BLOCK_BYTES - bufferCounter)]
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                                else -> {
 | 
				
			||||||
 | 
					                                    0U
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        bufferCounter = chunk.size - (BLOCK_BYTES - bufferCounter)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Encrypt fed data and return it alongside the randomly chosen initialization vector
 | 
				
			||||||
 | 
					     * @return Encrypted data and initialization vector
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fun encrypt(): EncryptedDataAndInitializationVector {
 | 
				
			||||||
 | 
					        if (bufferCounter > 0) {
 | 
				
			||||||
 | 
					            val lastBlockPadded = padToBlock(buffer)
 | 
				
			||||||
 | 
					            if (lastBlockPadded.size > BLOCK_BYTES) {
 | 
				
			||||||
 | 
					                val chunks = lastBlockPadded.chunked(BLOCK_BYTES).map { it.toUByteArray() }
 | 
				
			||||||
 | 
					                output += consumeBlock(chunks[0])
 | 
				
			||||||
 | 
					                output += consumeBlock(chunks[1])
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                output += consumeBlock(lastBlockPadded)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return EncryptedDataAndInitializationVector(
 | 
				
			||||||
 | 
					            output.reversed().foldRight(UByteArray(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes },
 | 
				
			||||||
 | 
					            initVector
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Decrypt data
 | 
				
			||||||
 | 
					     * @return Decrypted data
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fun decrypt(): UByteArray {
 | 
				
			||||||
 | 
					        val removePaddingCount = output.last().last()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val removedPadding = if (removePaddingCount > 0U && removePaddingCount < 16U) {
 | 
				
			||||||
 | 
					            output.last().dropLast(removePaddingCount.toInt() and 0x7F)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            output.last().toList()
 | 
				
			||||||
 | 
					        }.toUByteArray()
 | 
				
			||||||
 | 
					        val preparedOutput = (output.dropLast(1) + listOf(removedPadding))
 | 
				
			||||||
 | 
					        //JS compiler freaks out here if we don't supply exact type
 | 
				
			||||||
 | 
					        val reversed : List<UByteArray> = preparedOutput.reversed() as List<UByteArray>
 | 
				
			||||||
 | 
					        val folded : UByteArray = reversed.foldRight(UByteArray(0) { 0U }) { uByteArray, acc ->
 | 
				
			||||||
 | 
					            acc + uByteArray
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return folded
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun appendToBuffer(array: UByteArray, start: Int) {
 | 
				
			||||||
 | 
					        array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
 | 
				
			||||||
 | 
					        bufferCounter += array.size
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun consumeBlock(data: UByteArray): UByteArray {
 | 
				
			||||||
 | 
					        return when (mode) {
 | 
				
			||||||
 | 
					            Mode.ENCRYPT -> {
 | 
				
			||||||
 | 
					                currentOutput = if (currentOutput.isEmpty()) {
 | 
				
			||||||
 | 
					                    println("IV: $initVector")
 | 
				
			||||||
 | 
					                    AesPure.encrypt(aesKey, data xor initVector)
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    AesPure.encrypt(aesKey, data xor currentOutput)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                currentOutput
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Mode.DECRYPT -> {
 | 
				
			||||||
 | 
					                if (currentOutput.isEmpty()) {
 | 
				
			||||||
 | 
					                    currentOutput = AesPure.decrypt(aesKey, data) xor initVector
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    currentOutput = AesPure.decrypt(aesKey, data) xor previousEncrypted
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                previousEncrypted = data
 | 
				
			||||||
 | 
					                currentOutput
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					data class EncryptedDataAndInitializationVector(val encryptedData : UByteArray, val initilizationVector : UByteArray) {
 | 
				
			||||||
 | 
					    override fun equals(other: Any?): Boolean {
 | 
				
			||||||
 | 
					        if (this === other) return true
 | 
				
			||||||
 | 
					        if (other == null || this::class != other::class) return false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        other as EncryptedDataAndInitializationVector
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!encryptedData.contentEquals(other.encryptedData)) return false
 | 
				
			||||||
 | 
					        if (!initilizationVector.contentEquals(other.initilizationVector)) return false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun hashCode(): Int {
 | 
				
			||||||
 | 
					        var result = encryptedData.contentHashCode()
 | 
				
			||||||
 | 
					        result = 31 * result + initilizationVector.contentHashCode()
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
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