|
|
|
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
|
|
|
|
|
|
|
|
import Foundation
|
|
|
|
import Sodium
|
|
|
|
import Clibsodium
|
|
|
|
import Curve25519Kit
|
|
|
|
|
|
|
|
// MARK: - Box
|
|
|
|
|
|
|
|
public extension Crypto.Size {
|
|
|
|
static let publicKey: Crypto.Size = Crypto.Size(id: "publicKey") { $0.sign.PublicKeyBytes }
|
|
|
|
static let secretKey: Crypto.Size = Crypto.Size(id: "secretKey") { $0.sign.SecretKeyBytes }
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Sign
|
|
|
|
|
|
|
|
public extension Crypto.Action {
|
|
|
|
static func toX25519(ed25519PublicKey: Bytes) -> Crypto.Action {
|
|
|
|
return Crypto.Action(id: "toX25519", args: [ed25519PublicKey]) { sodium in
|
|
|
|
sodium.sign.toX25519(ed25519PublicKey: ed25519PublicKey)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static func toX25519(ed25519SecretKey: Bytes) -> Crypto.Action {
|
|
|
|
return Crypto.Action(id: "toX25519", args: [ed25519SecretKey]) { sodium in
|
|
|
|
sodium.sign.toX25519(ed25519SecretKey: ed25519SecretKey)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public extension Crypto.AuthenticationSignature {
|
|
|
|
static func signature(message: Bytes, secretKey: Bytes) -> Crypto.AuthenticationSignature {
|
|
|
|
return Crypto.AuthenticationSignature(id: "signature", args: [message, secretKey]) { sodium in
|
|
|
|
sodium.sign.signature(message: message, secretKey: secretKey).map { .standard(signature: $0) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public extension Crypto.Verification {
|
|
|
|
static func signature(message: Bytes, publicKey: Bytes, signature: Bytes) -> Crypto.Verification {
|
|
|
|
return Crypto.Verification(id: "signature", args: [message, publicKey, signature]) { sodium in
|
|
|
|
sodium.sign.verify(message: message, publicKey: publicKey, signature: signature)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Ed25519
|
|
|
|
|
|
|
|
public extension Crypto.KeyPairType {
|
|
|
|
static func x25519KeyPair() -> Crypto.KeyPairType {
|
|
|
|
return Crypto.KeyPairType(id: "x25519KeyPair") {
|
|
|
|
let keyPair: ECKeyPair = Curve25519.generateKeyPair()
|
|
|
|
|
|
|
|
return KeyPair(publicKey: Array(keyPair.publicKey), secretKey: Array(keyPair.privateKey))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static func ed25519KeyPair(
|
|
|
|
seed: Data? = nil,
|
|
|
|
using dependencies: Dependencies = Dependencies()
|
|
|
|
) -> Crypto.KeyPairType {
|
|
|
|
return Crypto.KeyPairType(id: "ed25519KeyPair") {
|
|
|
|
let pkSize: Int = dependencies[singleton: .crypto].size(.publicKey)
|
|
|
|
let skSize: Int = dependencies[singleton: .crypto].size(.secretKey)
|
|
|
|
var edPK: [UInt8] = [UInt8](repeating: 0, count: pkSize)
|
|
|
|
var edSK: [UInt8] = [UInt8](repeating: 0, count: skSize)
|
|
|
|
var targetSeed: [UInt8] = ((seed ?? (try? Randomness.generateRandomBytes(numberBytes: skSize)))
|
|
|
|
.map { Array($0) })
|
|
|
|
.defaulting(to: [])
|
|
|
|
|
|
|
|
// Generate the key
|
|
|
|
guard Sodium.lib_crypto_sign_ed25519_seed_keypair(&edPK, &edSK, &targetSeed) == 0 else {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return KeyPair(publicKey: edPK, secretKey: edSK)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public extension Crypto.Action {
|
|
|
|
static func signEd25519(data: Bytes, keyPair: KeyPair) -> Crypto.Action {
|
|
|
|
return Crypto.Action(id: "signEd25519", args: [data, keyPair]) {
|
|
|
|
let ecKeyPair: ECKeyPair = try ECKeyPair(
|
|
|
|
publicKeyData: Data(keyPair.publicKey),
|
|
|
|
privateKeyData: Data(keyPair.secretKey)
|
|
|
|
)
|
|
|
|
|
|
|
|
return try Ed25519.sign(Data(data), with: ecKeyPair).bytes
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public extension Crypto.Verification {
|
|
|
|
static func signatureEd25519(_ signature: Data, publicKey: Data, data: Data) -> Crypto.Verification {
|
|
|
|
return Crypto.Verification(id: "signatureEd25519", args: [signature, publicKey, data]) {
|
|
|
|
return ((try? Ed25519.verifySignature(signature, publicKey: publicKey, data: data)) == true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|