// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved. // // stringlint:disable import Foundation import Sodium import Clibsodium import Curve25519Kit import SessionUtilitiesKit // MARK: - Generic Hash public extension Crypto.Action { static func hash(message: Bytes, key: Bytes?) -> Crypto.Action { return Crypto.Action(id: "hash", args: [message, key]) { Sodium().genericHash.hash(message: message, key: key) } } static func hash(message: Bytes, outputLength: Int) -> Crypto.Action { return Crypto.Action(id: "hashOutputLength", args: [message, outputLength]) { Sodium().genericHash.hash(message: message, outputLength: outputLength) } } static func hashSaltPersonal( message: Bytes, outputLength: Int, key: Bytes? = nil, salt: Bytes, personal: Bytes ) -> Crypto.Action { return Crypto.Action( id: "hashSaltPersonal", args: [message, outputLength, key, salt, personal] ) { var output: [UInt8] = [UInt8](repeating: 0, count: outputLength) let result = crypto_generichash_blake2b_salt_personal( &output, outputLength, message, UInt64(message.count), key, (key?.count ?? 0), salt, personal ) guard result == 0 else { return nil } return output } } } // MARK: - Sign public extension Crypto.Action { static func toX25519(ed25519PublicKey: Bytes) -> Crypto.Action { return Crypto.Action(id: "toX25519", args: [ed25519PublicKey]) { Sodium().sign.toX25519(ed25519PublicKey: ed25519PublicKey) } } static func toX25519(ed25519SecretKey: Bytes) -> Crypto.Action { return Crypto.Action(id: "toX25519", args: [ed25519SecretKey]) { Sodium().sign.toX25519(ed25519SecretKey: ed25519SecretKey) } } static func signature(message: Bytes, secretKey: Bytes) -> Crypto.Action { return Crypto.Action(id: "signature", args: [message, secretKey]) { Sodium().sign.signature(message: message, secretKey: secretKey) } } } 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().sign.verify(message: message, publicKey: publicKey, signature: signature) } } } // MARK: - Box public extension Crypto.Size { static let signature: Crypto.Size = Crypto.Size(id: "signature") { Sodium().sign.Bytes } static let publicKey: Crypto.Size = Crypto.Size(id: "publicKey") { Sodium().sign.PublicKeyBytes } } public extension Crypto.Action { static func seal(message: Bytes, recipientPublicKey: Bytes) -> Crypto.Action { return Crypto.Action(id: "seal", args: [message, recipientPublicKey]) { Sodium().box.seal(message: message, recipientPublicKey: recipientPublicKey) } } static func open(anonymousCipherText: Bytes, recipientPublicKey: Bytes, recipientSecretKey: Bytes) -> Crypto.Action { return Crypto.Action( id: "open", args: [anonymousCipherText, recipientPublicKey, recipientSecretKey] ) { Sodium().box.open( anonymousCipherText: anonymousCipherText, recipientPublicKey: recipientPublicKey, recipientSecretKey: recipientSecretKey ) } } } // MARK: - AeadXChaCha20Poly1305Ietf public extension Crypto.Size { static let aeadXChaCha20NonceBytes: Crypto.Size = Crypto.Size(id: "aeadXChaCha20NonceBytes") { Sodium().aead.xchacha20poly1305ietf.NonceBytes } } // MARK: - Ed25519 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) } } } 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)) } } }