Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ryunen344/tink-kmm
Google/Tink Mapper for KMM(Kotlin Multiplatform Mobile)
https://github.com/ryunen344/tink-kmm
android crypto kmm kotlin kotlin-multiplatform kotlin-native
Last synced: 2 months ago
JSON representation
Google/Tink Mapper for KMM(Kotlin Multiplatform Mobile)
- Host: GitHub
- URL: https://github.com/ryunen344/tink-kmm
- Owner: RyuNen344
- License: mit
- Created: 2022-04-19T15:16:57.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2024-05-16T21:51:22.000Z (8 months ago)
- Last Synced: 2024-05-20T00:14:38.362Z (8 months ago)
- Topics: android, crypto, kmm, kotlin, kotlin-multiplatform, kotlin-native
- Language: Kotlin
- Homepage:
- Size: 696 KB
- Stars: 14
- Watchers: 1
- Forks: 1
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
# Tink-KMM
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.ryunen344.tink/tink/badge.svg?style=plastic&gav=true)](https://maven-badges.herokuapp.com/maven-central/io.github.ryunen344.tink/tink)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![test](https://github.com/RyuNen344/tink-kmm/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/RyuNen344/tink-kmm/actions/workflows/test.yml)
[![codecov](https://codecov.io/gh/RyuNen344/tink-kmm/branch/main/graph/badge.svg?token=21Z06YR92T)](https://codecov.io/gh/RyuNen344/tink-kmm)
![badge-android](http://img.shields.io/badge/-android-6EDB8D.svg?style=flat)
![badge-ios](http://img.shields.io/badge/-ios-CDCDCD.svg?style=flat)
![badge-silicon](http://img.shields.io/badge/support-[AppleSilicon]-43BBFF.svg?style=flat)This is a repositoy of [Google/Tink](https://github.com/google/tink) Mapper for KMM(Kotlin Multiplatform Mobile)
This wrapper library allows you to use Tink Primitive Encryption in your Kotlin Multiplatform Mobile project.## Why this library?
KMM currently does not have a Crypto Library that can be used as a de facto standard.
Of course, we can implement encryption using the expect/actual modifier.
But, CCCrypto has a limitation of supported algorithm.(e.g, it can not be use AES-GCM)## Tink Primitives
| **Primitive** | **Interfaces** |
| ---------------------------------------------------- | ------------------------------ |
| Authenticated Encryption with Associated Data (AEAD) | AEAD |
| _Streaming_ AEAD | StreamingAEAD |
| _Deterministic_ AEAD | DeterministicAEAD |
| Message Authentication Code (MAC) | MAC |
| Pseudo Random Function Family (PRF) | Prf, PrfSet |
| Hybrid encryption | HybridEncrypt, HybridDecrypt |
| Digital signatures | PublicKeySign, PublicKeyVerify |### Supported primitives and their implementations
#### Primitives supported by language
| **Primitive** | **Java** | **Objective-C** | **Tink-KMM** |
| ------------------ | :------: | :-------------: | :----------: |
| AEAD | yes | yes | yes |
| Streaming AEAD | yes | **no** | **no** |
| Deterministic AEAD | yes | yes | yes |
| MAC | yes | yes | yes |
| PRF | yes | **no** | **no** |
| Digital signatures | yes | yes | yes |
| Hybrid encryption | yes | yes | yes |#### Primitive implementations supported by language
| **Primitive** | **Implementation** | **Java** | **Objective-C** | **Tink-KMM** |
| ------------------ | ------------------------------------- | :------: | :-------------: | :----------: |
| AEAD | AES-GCM | yes | yes | yes |
| | AES-GCM-SIV | yes | **no** | **no** |
| | AES-CTR-HMAC | yes | yes | yes |
| | AES-EAX | yes | yes | yes |
| | KMS Envelope | yes | **no** | **no** |
| | CHACHA20-POLY1305 | yes | **no** | **no** |
| | XCHACHA20-POLY1305 | yes | yes | yes |
| Streaming AEAD | AES-GCM-HKDF-STREAMING | yes | **no** | **no** |
| | AES-CTR-HMAC-STREAMING | yes | **no** | **no** |
| Deterministic AEAD | AES-SIV | yes | yes | yes |
| MAC | HMAC-SHA2 | yes | yes | yes |
| | AES-CMAC | yes | yes | yes |
| PRF | HKDF-SHA2 | yes | **no** | **no** |
| | HMAC-SHA2 | yes | **no** | **no** |
| | AES-CMAC | yes | **no** | **no** |
| Digital Signatures | ECDSA over NIST curves | yes | yes | yes |
| | Ed25519 | yes | yes | yes |
| | RSA-SSA-PKCS1 | yes | yes | yes |
| | RSA-SSA-PSS | yes | yes | yes |
| Hybrid Encryption | HPKE | yes | **no** | **no** |
| | ECIES with AEAD and HKDF | yes | yes | yes |
| | ECIES with DeterministicAEAD and HKDF | yes | **no** | **no** |## Compatibility
| **Version** | **Kotlin** | **Tink-android** | **Tink-ObjC** |
|---------------|:----------:| :--------------: | :-----------: |
| 0.0.1 | 1.8.20 | 1.7.0 | 1.7.0 |
| 0.0.2 ~ 0.0.3 | 1.8.21 | 1.7.0 | 1.7.0 |
| 0.0.4 | 1.8.22 | 1.7.0 | 1.7.0 |
| 0.0.5 | 1.9.0 | 1.7.0 | 1.7.0 |
| 0.0.6 | 1.9.10 | 1.7.0 | 1.7.0 |
| 0.0.7 | 1.9.21 | 1.7.0 | 1.7.0 |> **Warning**
> Tink-ObjC 1.7.0 has not been released to CocoaPods yet.
> so, you need to build Tink-ObjC 1.7.0 by yourself.
> you can use my fork [RyuNen344/tink](https://github.com/RyuNen344/tink), and [Makefile](Makefile) can be used as a reference about how to build Tink-ObjC 1.7.0.## Installation
add the following to your `settings.gradle` and `build.gradle` file:
```kotlin:settings.gradle
repositories {
mavenCentral()
}
``````kotlin:build.gradle
kotlin {
// if you want to use without CocoaPods, you need to link with your Tink.framework like below.
iosX64 {
binaries {
framework {
linkerOpts(
listOf(
"-framework",
"Tink",
"-Fpath/to/Tink.framework",
"-rpath",
"path/to/Tink.framework",
"-ObjC",
)
)
}
}
}commonMain {
dependencies {
implementation "io.github.ryunen344.tink:tink:$tink_kmm_version"
}
}
}
```## Usage
you can use Tink-KMM like java Tink.
### Initialization
```kotlin
import io.github.ryunen344.tink.aead.AeadConfig
import io.github.ryunen344.tink.aead.register
import io.github.ryunen344.tink.daead.DeterministicAeadConfig
import io.github.ryunen344.tink.daead.register
import io.github.ryunen344.tink.hybrid.HybridConfig
import io.github.ryunen344.tink.hybrid.register
import io.github.ryunen344.tink.mac.MacConfig
import io.github.ryunen344.tink.mac.register
import io.github.ryunen344.tink.signature.SignatureConfig
import io.github.ryunen344.tink.signature.registerAeadConfig.register()
DeterministicAeadConfig.register()
HybridConfig.register()
MacConfig.register()
SignatureConfig.register()
```### Generate new keys and keysets
```kotlin
import io.github.ryunen344.tink.KeyTemplateSet
import io.github.ryunen344.tink.KeysetHandleGenerator
import io.github.ryunen344.tink.generateNewKeysetHandleGenerator.generateNew(KeyTemplateSet.AES256_GCM.template())
```> **Note**
> Defined available key templates in [KeyTemplateSet](tink/src/commonMain/kotlin/io/github/ryunen344/tink/KeyTemplateSet.kt)### Serialize and Deserialize
#### Serialize with KeysetWriter
##### Cleartext
```kotlin:SerializeCleartext.kt
val writer = BinaryKeysetWriter()// 1. write keyset to writer
handle.writeCleartext(writer)// 2. get ByteArray from writer and save serialized somewhere
val serialized = writer.write()
```##### NoSecret
```kotlin:SerializeNoSecret.kt
val writer = BinaryKeysetWriter()// 1. write keyset to writer
handle.writeNoSecret(writer)// 2. get ByteArray from writer(if keyset has secret key, throw exception)
val serialized = writer.write()
```#### Deserialize with KeysetReader
##### Binary
```kotlin:Deserialize.kt
// read with AEAD
val masterKey: AEAD
KeysetHandleGenerator.read(serialized, masterKey)// read ByteArray from somewhere
KeysetHandleGenerator.readClearText(BinaryKeysetReader(serialized))// read json string from somewhere
KeysetHandleGenerator.readClearText(JsonKeysetReader("json string"))// read ByteArray with secret key from somewhere
KeysetHandleGenerator.readNoSecret(serialized)
```### Obtaining and using primitives
#### AEAD
```kotlin:Aead.kt
import io.github.ryunen344.tink.aead.Aead
import io.github.ryunen344.tink.KeyTemplateSet
import io.github.ryunen344.tink.KeysetHandleGenerator
import io.github.ryunen344.tink.generateNew
import io.github.ryunen344.tink.getPrimitive// 1. Generate the key material.
val handle = KeysetHandleGenerator.generateNew(KeyTemplateSet.AES256_GCM.template())// 2. Get the primitive.
val aead = handle.getPrimitive(Aead::class)// 3. Use the primitive to encrypt a plaintext,
val ciphertext = aead.encrypt(plaintext, associatedData)// ... or to decrypt a ciphertext.
val decrypted = aead.decrypt(ciphertext, associatedData)
```#### DeterministicAEAD
```kotlin:DeterministicAead.kt
import io.github.ryunen344.tink.daead.DeterministicAead
import io.github.ryunen344.tink.KeyTemplateSet
import io.github.ryunen344.tink.KeysetHandleGenerator
import io.github.ryunen344.tink.generateNew
import io.github.ryunen344.tink.getPrimitive// 1. Generate the key material.
val handle = KeysetHandleGenerator.generateNew(KeyTemplateSet.AES256_GCM.template())// 2. Get the primitive.
val daead = handle.getPrimitive(DeterministicAead::class)// 3. Use the primitive to encrypt a plaintext,
val ciphertext = daead.encrypt(plaintext, associatedData)// ... or to decrypt a ciphertext.
val decrypted = daead.decrypt(ciphertext, associatedData)
```#### HybridAEAD
```kotlin:HybridAead.kt
import io.github.ryunen344.tink.hybrid.HybridEncrypt
import io.github.ryunen344.tink.hybrid.HybridDecrypt
import io.github.ryunen344.tink.KeyTemplateSet
import io.github.ryunen344.tink.KeysetHandleGenerator
import io.github.ryunen344.tink.generateNew
import io.github.ryunen344.tink.getPrimitive
import io.github.ryunen344.tink.publicKeysetHandle// 1. Generate the key material.
val privateKeysetHandle = KeysetHandleGenerator.generateNew(KeyTemplateSet.ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM.template())
val publicKeysetHandle = privateKeysetHandle.publicKeysetHandle()// 2. Get the primitives.
val hybridEncrypt = publicKeysetHandle.getPrimitive(HybridEncrypt::class)
val hybridDecrypt = privateKeysetHandle.getPrimitive(HybridDecrypt::class)// 3. Use the primitives to encrypt and decrypt.
val ciphertext = hybridEncrypt.encrypt(plaintext, contextInfo)
val decrypted = hybridDecrypt.decrypt(ciphertext, contextInfo)
```#### MAC
```kotlin:Mac.kt
import io.github.ryunen344.tink.mac.Mac
import io.github.ryunen344.tink.KeyTemplateSet
import io.github.ryunen344.tink.KeysetHandleGenerator
import io.github.ryunen344.tink.generateNew
import io.github.ryunen344.tink.getPrimitive// 1. Generate the key material.
val handle = KeysetHandleGenerator.generateNew(KeyTemplateSet.HMAC_SHA256_128BITTAG.template())// 2. Get the primitive.
val mac = handle.getPrimitive(Mac::class)// 3. Use the primitive to compute a tag.
val tag = mac.computeMac(plaintext)// ... or to verify a tag.
mac.verifyMac(tag, plaintext)
```#### Signature
```kotlin:Signature.kt
import io.github.ryunen344.tink.signature.PublicKeySign
import io.github.ryunen344.tink.signature.PublicKeyVerify
import io.github.ryunen344.tink.KeyTemplateSet
import io.github.ryunen344.tink.KeysetHandleGenerator
import io.github.ryunen344.tink.generateNew
import io.github.ryunen344.tink.getPrimitive
import io.github.ryunen344.tink.publicKeysetHandle// 1. Generate the key material.
val privateHandle = KeysetHandleGenerator.generateNew(KeyTemplateSet.ECDSA_P256.template())
val publicHandle = privateHandle.publicKeysetHandle()// 2. Get the primitive.
val signer = privateHandle.getPrimitive(PublicKeySign::class)
val verifier = publicHandle.getPrimitive(PublicKeyVerify::class)// 3. Use the primitive to sign a message.
val signature = signer.sign(message)// ... or to verify a signature.
verifier.verify(signature, message)
```#### Swift(Optional)
This library also supports be used in Swift directory.
```swift
try! AeadConfig.companion.register()
let template = try! KeyTemplateSet.aes256Gcm.template()
let handle = try! KeysetHandleGenerator.companion.generateNew(keyTemplate: template)
let aead = try! KeysetHandleKt.getPrimitive(handle, kClass: TinkPrimitiveKt.aead) as! Aead
let ciphertext = try! aead.encrypt(plaintext, with: associatedData)
let decrypted = try! aead.decrypt(ciphertext, with: associatedData)
```