commit
ce24fc5dfc
@ -0,0 +1,34 @@
|
|||||||
|
package com.ionspin.kotlin.crypto.scalarmult
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Ugljesa Jovanovic
|
||||||
|
* ugljesa.jovanovic@ionspin.com
|
||||||
|
* on 15-Oct-2020
|
||||||
|
*/
|
||||||
|
const val crypto_scalarmult_BYTES = 32
|
||||||
|
const val crypto_scalarmult_SCALARBYTES = 32
|
||||||
|
|
||||||
|
expect object ScalarMultiplication {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function can be used to compute a shared secret q given a user's secret key and another user's public key.
|
||||||
|
* n is crypto_scalarmult_SCALARBYTES bytes long, p and the output are crypto_scalarmult_BYTES bytes long.
|
||||||
|
* q represents the X coordinate of a point on the curve. As a result, the number of possible keys is limited to
|
||||||
|
* the group size (≈2^252), which is smaller than the key space.
|
||||||
|
* For this reason, and to mitigate subtle attacks due to the fact many (p, n) pairs produce the same result,
|
||||||
|
* using the output of the multiplication q directly as a shared key is not recommended.
|
||||||
|
* A better way to compute a shared key is h(q ‖ pk1 ‖ pk2), with pk1 and pk2 being the public keys.
|
||||||
|
* By doing so, each party can prove what exact public key they intended to perform a key exchange with
|
||||||
|
* (for a given public key, 11 other public keys producing the same shared secret can be trivially computed).
|
||||||
|
* This can be achieved with the following code snippet:
|
||||||
|
*/
|
||||||
|
fun scalarMultiplication(secretKeyN : UByteArray, publicKeyP: UByteArray) : UByteArray
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a user's secret key n (crypto_scalarmult_SCALARBYTES bytes), the crypto_scalarmult_base() function
|
||||||
|
* computes the user's public key and puts it into q (crypto_scalarmult_BYTES bytes).
|
||||||
|
* crypto_scalarmult_BYTES and crypto_scalarmult_SCALARBYTES are provided for consistency,
|
||||||
|
* but it is safe to assume that crypto_scalarmult_BYTES == crypto_scalarmult_SCALARBYTES.
|
||||||
|
*/
|
||||||
|
fun scalarMultiplicationBase(secretKeyN : UByteArray) : UByteArray
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package com.ionspin.kotlin.crypto.scalarmult
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer
|
||||||
|
import com.ionspin.kotlin.crypto.util.toHexString
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Ugljesa Jovanovic
|
||||||
|
* ugljesa.jovanovic@ionspin.com
|
||||||
|
* on 15-Oct-2020
|
||||||
|
*/
|
||||||
|
class ScalarMultiplicationTest {
|
||||||
|
val aliceSecretKey = ubyteArrayOf(
|
||||||
|
0x77U, 0x07U, 0x6dU, 0x0aU, 0x73U, 0x18U, 0xa5U, 0x7dU, 0x3cU, 0x16U, 0xc1U,
|
||||||
|
0x72U, 0x51U, 0xb2U, 0x66U, 0x45U, 0xdfU, 0x4cU, 0x2fU, 0x87U, 0xebU, 0xc0U,
|
||||||
|
0x99U, 0x2aU, 0xb1U, 0x77U, 0xfbU, 0xa5U, 0x1dU, 0xb9U, 0x2cU, 0x2aU
|
||||||
|
)
|
||||||
|
|
||||||
|
val bobSecretKey = ubyteArrayOf(
|
||||||
|
0x5dU, 0xabU, 0x08U, 0x7eU, 0x62U, 0x4aU, 0x8aU, 0x4bU, 0x79U, 0xe1U, 0x7fU,
|
||||||
|
0x8bU, 0x83U, 0x80U, 0x0eU, 0xe6U, 0x6fU, 0x3bU, 0xb1U, 0x29U, 0x26U, 0x18U,
|
||||||
|
0xb6U, 0xfdU, 0x1cU, 0x2fU, 0x8bU, 0x27U, 0xffU, 0x88U, 0xe0U, 0xebU
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
val expectedAlicePublicKeyString = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"
|
||||||
|
val expectedBobPublickKeyString = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"
|
||||||
|
val expectedSharedSecretString = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testScalarMultiplication() {
|
||||||
|
LibsodiumInitializer.initializeWithCallback {
|
||||||
|
val alicePublicKey = ScalarMultiplication.scalarMultiplicationBase(aliceSecretKey)
|
||||||
|
assertTrue {
|
||||||
|
alicePublicKey.toHexString().equals(expectedAlicePublicKeyString)
|
||||||
|
}
|
||||||
|
val bobPublickKey = ScalarMultiplication.scalarMultiplicationBase(bobSecretKey)
|
||||||
|
assertTrue {
|
||||||
|
bobPublickKey.toHexString().equals(expectedBobPublickKeyString)
|
||||||
|
}
|
||||||
|
val aliceToBobSecret = ScalarMultiplication.scalarMultiplication(aliceSecretKey, bobPublickKey)
|
||||||
|
val bobToAliceSecret = ScalarMultiplication.scalarMultiplication(bobSecretKey, alicePublicKey)
|
||||||
|
assertTrue {
|
||||||
|
aliceToBobSecret.toHexString().equals(expectedSharedSecretString)
|
||||||
|
}
|
||||||
|
assertTrue {
|
||||||
|
bobToAliceSecret.toHexString().equals(expectedSharedSecretString)
|
||||||
|
}
|
||||||
|
println(aliceToBobSecret.toHexString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -232,8 +232,14 @@ interface JsSodiumInterface {
|
|||||||
fun crypto_stream_chacha20_xor(message : Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
|
fun crypto_stream_chacha20_xor(message : Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
|
||||||
fun crypto_stream_chacha20_xor_ic(message : Uint8Array, nonce: Uint8Array, initialCounter: UInt, key: Uint8Array) : Uint8Array
|
fun crypto_stream_chacha20_xor_ic(message : Uint8Array, nonce: Uint8Array, initialCounter: UInt, key: Uint8Array) : Uint8Array
|
||||||
|
|
||||||
|
// ---- Stream end ----
|
||||||
|
|
||||||
|
// ---- Scalar multiplication ----
|
||||||
|
|
||||||
|
fun crypto_scalarmult(privateKey: Uint8Array, publicKey: Uint8Array) : Uint8Array
|
||||||
|
fun crypto_scalarmult_base(privateKey: Uint8Array) : Uint8Array
|
||||||
|
|
||||||
|
// ---- Scalar multiplication end ----
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.ionspin.kotlin.crypto.scalarmult
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.getSodium
|
||||||
|
import ext.libsodium.com.ionspin.kotlin.crypto.toUByteArray
|
||||||
|
import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array
|
||||||
|
|
||||||
|
actual object ScalarMultiplication {
|
||||||
|
/**
|
||||||
|
* This function can be used to compute a shared secret q given a user's secret key and another user's public key.
|
||||||
|
* n is crypto_scalarmult_SCALARBYTES bytes long, p and the output are crypto_scalarmult_BYTES bytes long.
|
||||||
|
* q represents the X coordinate of a point on the curve. As a result, the number of possible keys is limited to
|
||||||
|
* the group size (≈2^252), which is smaller than the key space.
|
||||||
|
* For this reason, and to mitigate subtle attacks due to the fact many (p, n) pairs produce the same result,
|
||||||
|
* using the output of the multiplication q directly as a shared key is not recommended.
|
||||||
|
* A better way to compute a shared key is h(q ‖ pk1 ‖ pk2), with pk1 and pk2 being the public keys.
|
||||||
|
* By doing so, each party can prove what exact public key they intended to perform a key exchange with
|
||||||
|
* (for a given public key, 11 other public keys producing the same shared secret can be trivially computed).
|
||||||
|
* This can be achieved with the following code snippet:
|
||||||
|
*/
|
||||||
|
actual fun scalarMultiplication(secretKeyN: UByteArray, publicKeyP: UByteArray): UByteArray {
|
||||||
|
val result = getSodium().crypto_scalarmult(secretKeyN.toUInt8Array(), publicKeyP.toUInt8Array())
|
||||||
|
|
||||||
|
return result.toUByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a user's secret key n (crypto_scalarmult_SCALARBYTES bytes), the crypto_scalarmult_base() function
|
||||||
|
* computes the user's public key and puts it into q (crypto_scalarmult_BYTES bytes).
|
||||||
|
* crypto_scalarmult_BYTES and crypto_scalarmult_SCALARBYTES are provided for consistency,
|
||||||
|
* but it is safe to assume that crypto_scalarmult_BYTES == crypto_scalarmult_SCALARBYTES.
|
||||||
|
*/
|
||||||
|
actual fun scalarMultiplicationBase(
|
||||||
|
secretKeyN: UByteArray
|
||||||
|
): UByteArray {
|
||||||
|
val result = getSodium().crypto_scalarmult_base( secretKeyN.toUInt8Array())
|
||||||
|
|
||||||
|
return result.toUByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.ionspin.kotlin.crypto.scalarmult
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
||||||
|
|
||||||
|
actual object ScalarMultiplication {
|
||||||
|
/**
|
||||||
|
* This function can be used to compute a shared secret q given a user's secret key and another user's public key.
|
||||||
|
* n is crypto_scalarmult_SCALARBYTES bytes long, p and the output are crypto_scalarmult_BYTES bytes long.
|
||||||
|
* q represents the X coordinate of a point on the curve. As a result, the number of possible keys is limited to
|
||||||
|
* the group size (≈2^252), which is smaller than the key space.
|
||||||
|
* For this reason, and to mitigate subtle attacks due to the fact many (p, n) pairs produce the same result,
|
||||||
|
* using the output of the multiplication q directly as a shared key is not recommended.
|
||||||
|
* A better way to compute a shared key is h(q ‖ pk1 ‖ pk2), with pk1 and pk2 being the public keys.
|
||||||
|
* By doing so, each party can prove what exact public key they intended to perform a key exchange with
|
||||||
|
* (for a given public key, 11 other public keys producing the same shared secret can be trivially computed).
|
||||||
|
* This can be achieved with the following code snippet:
|
||||||
|
*/
|
||||||
|
actual fun scalarMultiplication(secretKeyN: UByteArray, publicKeyP: UByteArray): UByteArray {
|
||||||
|
val result = UByteArray(crypto_scalarmult_BYTES)
|
||||||
|
|
||||||
|
sodium.crypto_scalarmult(result.asByteArray(), secretKeyN.asByteArray(), publicKeyP.asByteArray())
|
||||||
|
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a user's secret key n (crypto_scalarmult_SCALARBYTES bytes), the crypto_scalarmult_base() function
|
||||||
|
* computes the user's public key and puts it into q (crypto_scalarmult_BYTES bytes).
|
||||||
|
* crypto_scalarmult_BYTES and crypto_scalarmult_SCALARBYTES are provided for consistency,
|
||||||
|
* but it is safe to assume that crypto_scalarmult_BYTES == crypto_scalarmult_SCALARBYTES.
|
||||||
|
*/
|
||||||
|
actual fun scalarMultiplicationBase(
|
||||||
|
secretKeyN: UByteArray
|
||||||
|
): UByteArray {
|
||||||
|
val result = UByteArray(crypto_scalarmult_BYTES)
|
||||||
|
|
||||||
|
sodium.crypto_scalarmult_base(result.asByteArray(), secretKeyN.asByteArray())
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package com.ionspin.kotlin.crypto.scalarmult
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.util.toPtr
|
||||||
|
import kotlinx.cinterop.pin
|
||||||
|
import libsodium.crypto_scalarmult
|
||||||
|
import libsodium.crypto_scalarmult_base
|
||||||
|
|
||||||
|
actual object ScalarMultiplication {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function can be used to compute a shared secret q given a user's secret key and another user's public key.
|
||||||
|
* n is crypto_scalarmult_SCALARBYTES bytes long, p and the output are crypto_scalarmult_BYTES bytes long.
|
||||||
|
* q represents the X coordinate of a point on the curve. As a result, the number of possible keys is limited to
|
||||||
|
* the group size (≈2^252), which is smaller than the key space.
|
||||||
|
* For this reason, and to mitigate subtle attacks due to the fact many (p, n) pairs produce the same result,
|
||||||
|
* using the output of the multiplication q directly as a shared key is not recommended.
|
||||||
|
* A better way to compute a shared key is h(q ‖ pk1 ‖ pk2), with pk1 and pk2 being the public keys.
|
||||||
|
* By doing so, each party can prove what exact public key they intended to perform a key exchange with
|
||||||
|
* (for a given public key, 11 other public keys producing the same shared secret can be trivially computed).
|
||||||
|
* This can be achieved with the following code snippet:
|
||||||
|
*/
|
||||||
|
actual fun scalarMultiplication(secretKeyN: UByteArray, publicKeyP: UByteArray): UByteArray {
|
||||||
|
val result = UByteArray(crypto_scalarmult_BYTES)
|
||||||
|
val resultPinned = result.pin()
|
||||||
|
val secretKeyNPinned = secretKeyN.pin()
|
||||||
|
val publicKeyPPinned = publicKeyP.pin()
|
||||||
|
|
||||||
|
crypto_scalarmult(resultPinned.toPtr(), secretKeyNPinned.toPtr(), publicKeyPPinned.toPtr())
|
||||||
|
|
||||||
|
resultPinned.unpin()
|
||||||
|
secretKeyNPinned.unpin()
|
||||||
|
publicKeyPPinned.unpin()
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a user's secret key n (crypto_scalarmult_SCALARBYTES bytes), the crypto_scalarmult_base() function
|
||||||
|
* computes the user's public key and puts it into q (crypto_scalarmult_BYTES bytes).
|
||||||
|
* crypto_scalarmult_BYTES and crypto_scalarmult_SCALARBYTES are provided for consistency,
|
||||||
|
* but it is safe to assume that crypto_scalarmult_BYTES == crypto_scalarmult_SCALARBYTES.
|
||||||
|
*/
|
||||||
|
actual fun scalarMultiplicationBase(
|
||||||
|
secretKeyN: UByteArray
|
||||||
|
): UByteArray {
|
||||||
|
val result = UByteArray(crypto_scalarmult_BYTES)
|
||||||
|
val resultPinned = result.pin()
|
||||||
|
val secretKeyNPinned = secretKeyN.pin()
|
||||||
|
|
||||||
|
crypto_scalarmult_base(resultPinned.toPtr(), secretKeyNPinned.toPtr())
|
||||||
|
|
||||||
|
resultPinned.unpin()
|
||||||
|
secretKeyNPinned.unpin()
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -144,7 +144,7 @@ kotlin {
|
|||||||
implementation(kotlin(Deps.Common.stdLib))
|
implementation(kotlin(Deps.Common.stdLib))
|
||||||
implementation(kotlin(Deps.Common.test))
|
implementation(kotlin(Deps.Common.test))
|
||||||
implementation(Deps.Common.kotlinBigNum)
|
implementation(Deps.Common.kotlinBigNum)
|
||||||
implementation(project(":multiplatform-crypto-delegated"))
|
implementation(project(":multiplatform-crypto-libsodium-bindings"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val commonTest by getting {
|
val commonTest by getting {
|
||||||
|
@ -1,28 +1,12 @@
|
|||||||
package com.ionspin.kotlin.crypto.sample
|
package com.ionspin.kotlin.crypto.sample
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.Crypto
|
import com.ionspin.kotlin.crypto.util.LibsodiumRandom
|
||||||
import com.ionspin.kotlin.crypto.CryptoInitializerDelegated
|
|
||||||
import com.ionspin.kotlin.crypto.CryptoPrimitives
|
|
||||||
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
|
||||||
import com.ionspin.kotlin.crypto.util.toHexString
|
import com.ionspin.kotlin.crypto.util.toHexString
|
||||||
|
|
||||||
|
|
||||||
object Sample {
|
object Sample {
|
||||||
fun runSample() {
|
fun runSample() {
|
||||||
println("Initializing crypto library")
|
val random = LibsodiumRandom.buf(32)
|
||||||
CryptoInitializerDelegated.initializeWithCallback {
|
println("Random: ${random.toHexString()}")
|
||||||
blake2b()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun blake2b() {
|
|
||||||
println("Blake2b updateable")
|
|
||||||
val blake2bUpdateable = CryptoPrimitives.Blake2b.updateable()
|
|
||||||
blake2bUpdateable.update("test".encodeToUByteArray())
|
|
||||||
println(blake2bUpdateable.digest().toHexString())
|
|
||||||
println("Blake2b stateless")
|
|
||||||
val statelessResult = CryptoPrimitives.Blake2b.stateless("test".encodeToUByteArray())
|
|
||||||
println("Blake2b stateless: ${statelessResult.toHexString()}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import com.ionspin.kotlin.crypto.sample.Sample
|
|||||||
import kotlin.time.ExperimentalTime
|
import kotlin.time.ExperimentalTime
|
||||||
|
|
||||||
@ExperimentalTime
|
@ExperimentalTime
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
|
||||||
Sample.runSample()
|
Sample.runSample()
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import com.ionspin.kotlin.crypto.sample.Sample
|
import com.ionspin.kotlin.crypto.sample.Sample
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
Sample.runSample()
|
Sample.runSample()
|
||||||
}
|
}
|
||||||
|
@ -104,8 +104,8 @@ native libsodium library.
|
|||||||
| crypto_pwhash_str | :heavy_check_mark: |
|
| crypto_pwhash_str | :heavy_check_mark: |
|
||||||
| crypto_pwhash_str_needs_rehash | :heavy_check_mark: |
|
| crypto_pwhash_str_needs_rehash | :heavy_check_mark: |
|
||||||
| crypto_pwhash_str_verify | :heavy_check_mark: |
|
| crypto_pwhash_str_verify | :heavy_check_mark: |
|
||||||
| crypto_scalarmult | |
|
| crypto_scalarmult | :heavy_check_mark: |
|
||||||
| crypto_scalarmult_base | |
|
| crypto_scalarmult_base | :heavy_check_mark: |
|
||||||
| crypto_scalarmult_ristretto255 | not present in LazySodium |
|
| crypto_scalarmult_ristretto255 | not present in LazySodium |
|
||||||
| crypto_scalarmult_ristretto255_base | not present in LazySodium |
|
| crypto_scalarmult_ristretto255_base | not present in LazySodium |
|
||||||
| crypto_secretbox_detached | :heavy_check_mark: |
|
| crypto_secretbox_detached | :heavy_check_mark: |
|
||||||
@ -156,6 +156,7 @@ native libsodium library.
|
|||||||
|
|
||||||
## Constants
|
## Constants
|
||||||
| Constant name| Implemented |
|
| Constant name| Implemented |
|
||||||
|
|-------------|-------------|
|
||||||
| SODIUM_LIBRARY_VERSION_MAJOR | |
|
| SODIUM_LIBRARY_VERSION_MAJOR | |
|
||||||
| SODIUM_LIBRARY_VERSION_MINOR | |
|
| SODIUM_LIBRARY_VERSION_MINOR | |
|
||||||
| crypto_aead_chacha20poly1305_ABYTES | |
|
| crypto_aead_chacha20poly1305_ABYTES | |
|
||||||
@ -311,8 +312,8 @@ native libsodium library.
|
|||||||
| crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE | |
|
| crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE | |
|
||||||
| crypto_pwhash_scryptsalsa208sha256_SALTBYTES | |
|
| crypto_pwhash_scryptsalsa208sha256_SALTBYTES | |
|
||||||
| crypto_pwhash_scryptsalsa208sha256_STRBYTES | |
|
| crypto_pwhash_scryptsalsa208sha256_STRBYTES | |
|
||||||
| crypto_scalarmult_BYTES | |
|
| crypto_scalarmult_BYTES | :heavy_check_mark: |
|
||||||
| crypto_scalarmult_SCALARBYTES | |
|
| crypto_scalarmult_SCALARBYTES | :heavy_check_mark: |
|
||||||
| crypto_scalarmult_curve25519_BYTES | :heavy_check_mark: |
|
| crypto_scalarmult_curve25519_BYTES | :heavy_check_mark: |
|
||||||
| crypto_scalarmult_curve25519_SCALARBYTES | |
|
| crypto_scalarmult_curve25519_SCALARBYTES | |
|
||||||
| crypto_scalarmult_ed25519_BYTES | |
|
| crypto_scalarmult_ed25519_BYTES | |
|
||||||
|
Loading…
x
Reference in New Issue
Block a user