2019-07-20 20:02:37 +02:00
|
|
|
[](https://travis-ci.com/ionspin/kotlin-multiplatform-crypto)
|
|
|
|

|
|
|
|
|
2019-07-20 11:39:26 +02:00
|
|
|
# Kotlin Multiplatform Crypto Library
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
2019-09-23 23:14:55 +02:00
|
|
|
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.
|
|
|
|
|
2019-07-20 11:39:26 +02:00
|
|
|
## Notes & Roadmap
|
|
|
|
|
|
|
|
**The API will move fast and break often until v1.0**
|
|
|
|
|
2019-07-21 12:36:10 +02:00
|
|
|
Make SHA hashes "updatable" like Blake2b
|
2019-07-20 18:59:37 +02:00
|
|
|
|
|
|
|
After that tenative plan is to add 25519 curve based signing and key exchange next.
|
2019-07-20 11:39:26 +02:00
|
|
|
|
|
|
|
## Should I use this in production?
|
|
|
|
|
2019-09-19 23:53:23 +02:00
|
|
|
No.
|
|
|
|
|
|
|
|
## Should I use this in code that is critical in any way, shape or form?
|
|
|
|
|
|
|
|
No.
|
|
|
|
|
|
|
|
## Why?
|
|
|
|
|
|
|
|
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.
|
2019-07-20 11:39:26 +02:00
|
|
|
|
2019-09-25 00:42:01 +02:00
|
|
|
## Integration
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-07-20 18:59:37 +02:00
|
|
|
## Hashing functions
|
|
|
|
* Blake2b
|
|
|
|
* SHA512
|
|
|
|
* SHA256
|
|
|
|
|
2019-09-25 00:42:01 +02:00
|
|
|
## Symmetric cipher (Currently only available only in 0.0.3-SNAPSHOT)
|
2019-09-19 23:53:23 +02:00
|
|
|
* AES
|
2019-09-23 23:14:55 +02:00
|
|
|
* Modes: CBC, CTR
|
2020-01-10 23:58:28 +01:00
|
|
|
|
|
|
|
## Key Derivation
|
|
|
|
|
|
|
|
* Argon2
|
|
|
|
|
|
|
|
## AEAD
|
2019-09-19 23:53:23 +02:00
|
|
|
|
2019-07-20 18:59:37 +02:00
|
|
|
More to come.
|
|
|
|
|
2019-07-20 11:39:26 +02:00
|
|
|
## Integration
|
|
|
|
|
|
|
|
#### Gradle
|
|
|
|
```kotlin
|
2019-12-26 21:36:03 +01:00
|
|
|
implementation("com.ionspin.kotlin:multiplatform-crypto:0.0.2")
|
2019-07-20 11:39:26 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
#### Snapshot builds
|
|
|
|
```kotlin
|
|
|
|
repositories {
|
|
|
|
maven {
|
|
|
|
url = uri("https://oss.sonatype.org/content/repositories/snapshots")
|
|
|
|
}
|
|
|
|
}
|
2019-12-26 21:36:03 +01:00
|
|
|
implementation("com.ionspin.kotlin:multiplatform-crypto:0.0.3-SNAPSHOT")
|
2019-07-20 11:39:26 +02:00
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
## Usage
|
|
|
|
|
2019-07-21 12:36:10 +02:00
|
|
|
### Hashes
|
|
|
|
|
|
|
|
Hashes are provided in two versions, "stateless", usually the companion object of the hash,
|
|
|
|
which takes the data to be hashed in one go, and "updatable" which can be fed data in chunks.
|
|
|
|
|
|
|
|
|
|
|
|
#### Blake2b
|
2019-07-20 18:59:37 +02:00
|
|
|
|
|
|
|
You can use Blake 2b in two modes
|
|
|
|
|
2019-07-21 12:36:10 +02:00
|
|
|
##### Stateless version
|
2019-07-20 18:59:37 +02:00
|
|
|
You need to deliver the complete data that is to be hashed in one go
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
val input = "abc"
|
|
|
|
val result = Blake2b.digest(input)
|
|
|
|
```
|
|
|
|
|
|
|
|
Result is returned as a `Array<Byte>`
|
|
|
|
|
2019-07-21 12:36:10 +02:00
|
|
|
##### Updatable instance version
|
2019-07-20 18:59:37 +02:00
|
|
|
You can create an instance and feed the data by using `update(input : Array<Byte>)` call. Once all data is supplied,
|
2019-07-21 12:36:10 +02:00
|
|
|
you should call `digest()` or `digestString()` convenience method that converts the `Array<Byte>` into hexadecimal string.
|
2019-07-20 18:59:37 +02:00
|
|
|
|
|
|
|
If you want to use Blake2b with a key, you should supply it when creating the `Blake2b` instance.
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
val test = "abc"
|
|
|
|
val key = "key"
|
|
|
|
val blake2b = Blake2b(key)
|
|
|
|
blake2b.update(test)
|
|
|
|
val result = blake2b.digest()
|
|
|
|
```
|
|
|
|
|
|
|
|
After digest is called, the instance is reset and can be reused (Keep in mind key stays the same for the particular instance).
|
2019-07-21 12:36:10 +02:00
|
|
|
#### SHA2 (SHA256 and SHA512)
|
|
|
|
|
|
|
|
##### Stateless version
|
2019-07-20 18:59:37 +02:00
|
|
|
|
|
|
|
You need to deliver the complete data that is to be hashed in one go. You can either provide the `Array<Byte>` as input
|
|
|
|
or `String`. Result is always returned as `Array<Byte>` (At least in verision 0.0.1)
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
val input = "abc"
|
|
|
|
val result = Sha256.digest(input)
|
|
|
|
```
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
val input ="abc"
|
|
|
|
val result = Sha512.digest(message = input.encodeToByteArray().map { it.toUByte() }.toTypedArray())
|
|
|
|
```
|
|
|
|
|
|
|
|
Result is returned as a `Array<Byte>`
|
|
|
|
|
2019-07-21 12:36:10 +02:00
|
|
|
##### Updateable version
|
|
|
|
|
|
|
|
Or you can use the updatable instance version
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
val sha256 = Sha256()
|
|
|
|
sha256.update("abc")
|
|
|
|
val result = sha256.digest()
|
|
|
|
```
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
val sha512 = Sha512()
|
|
|
|
sha512.update("abc")
|
|
|
|
val result = sha512.digest()
|
|
|
|
```
|
2019-09-23 23:14:55 +02:00
|
|
|
### Symmetric encryption
|
|
|
|
|
|
|
|
#### AES
|
|
|
|
|
|
|
|
Aes is available with CBC and CTR mode through `AesCbc` and `AesCtr` classes/objects.
|
|
|
|
Similarly to hashes you can either use stateless or updateable version.
|
|
|
|
|
|
|
|
Initialization vector, or counter states are chosen by the SDK automaticaly, and returned alongside encrypted data
|
|
|
|
|
|
|
|
##### Stateless AesCbc and AesCtr
|
|
|
|
|
|
|
|
AesCtr
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
val keyString = "4278b840fb44aaa757c1bf04acbe1a3e"
|
|
|
|
val key = AesKey.Aes128Key(keyString)
|
|
|
|
val plainText = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
|
|
|
|
|
|
|
|
val encryptedDataAndInitializationVector = AesCtr.encrypt(key, plainText.hexStringToUByteArray())
|
|
|
|
val decrypted = AesCtr.decrypt(
|
|
|
|
key,
|
|
|
|
encryptedDataAndInitializationVector.encryptedData,
|
|
|
|
encryptedDataAndInitializationVector.initialCounter
|
|
|
|
)
|
|
|
|
plainText == decrypted.toHexString()
|
|
|
|
```
|
|
|
|
|
|
|
|
AesCbc
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
|
|
|
|
val keyString = "4278b840fb44aaa757c1bf04acbe1a3e"
|
|
|
|
val key = AesKey.Aes128Key(keyString)
|
|
|
|
|
|
|
|
val plainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
|
|
|
|
|
|
|
|
val encryptedDataAndInitializationVector = AesCbc.encrypt(key, plainText.hexStringToUByteArray())
|
|
|
|
val decrypted = AesCbc.decrypt(
|
|
|
|
key,
|
|
|
|
encryptedDataAndInitializationVector.encryptedData,
|
|
|
|
encryptedDataAndInitializationVector.initilizationVector
|
|
|
|
)
|
|
|
|
plainText == decrypted.toHexString()
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-07-21 12:36:10 +02:00
|
|
|
|
2019-07-20 18:59:37 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-07-20 11:39:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
|