Compare commits

..

1 Commits

Author SHA1 Message Date
Jack Lloyd
e3fb642a8c Add a better HKDF test 2020-10-08 19:16:07 -04:00
18 changed files with 226 additions and 375 deletions

View File

@ -1,64 +0,0 @@
name: CI
on: [pull_request]
jobs:
build_and_test:
name: Build and Test
runs-on: macOS-latest
env:
PKG_CONFIG_PATH: ${{ github.workspace }}/libsignal-ffi/target/debug
steps:
- name: Install nightly rust (needed for libsignal-ffi)
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
override: true
profile: minimal
- name: Configure git to use HTTPS
run: git config --global url."https://github.com".insteadOf ssh://git@github.com
- name: Check out libsignal-protocol-swift
uses: actions/checkout@v2
- name: Check out libsignal-ffi
uses: actions/checkout@v2
with:
repository: signalapp/libsignal-ffi
path: libsignal-ffi
- name: Build libsignal-ffi
run: make -C libsignal-ffi
- name: Build libsignal-protocol-swift and run tests
run: swift test -v --enable-code-coverage -Xlinker -rpath -Xlinker $PKG_CONFIG_PATH
- name: Generate coverage report
run: xcrun llvm-cov show --format=html --instr-profile .build/x86_64-apple-macosx/debug/codecov/default.profdata .build/x86_64-apple-macosx/debug/*.xctest/Contents/MacOS/* Sources --output-dir coverage-report
- name: Upload coverage report
uses: actions/upload-artifact@v2
with:
name: Coverage
path: coverage-report
- name: Summarize coverage
run: xcrun llvm-cov report --instr-profile .build/x86_64-apple-macosx/debug/codecov/default.profdata .build/x86_64-apple-macosx/debug/*.xctest/Contents/MacOS/* Sources
lint:
name: Lint
runs-on: macOS-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: brew install swiftlint
- name: Run lint
run: swiftlint lint --reporter github-actions-logging

View File

@ -1,6 +1,8 @@
# Overview
**This repository has been folded into [libsignal-client](https://github.com/signalapp/libsignal-client).**
libsignal-protocol-swift is a Swift binding to libsignal-protocol-rust via libsignal-ffi
Work in progress. Subject to change without notice, use outside Signal not yet recommended.
# Legal things
## Cryptography Notice

View File

@ -1,5 +1,4 @@
import SignalFfi
import Foundation
public struct DisplayableFingerprint {
public let formatted: String
@ -41,22 +40,18 @@ public struct NumericFingerprintGenerator {
self.iterations = iterations
}
public func create<LocalBytes, RemoteBytes>(version: Int,
localIdentifier: LocalBytes,
localKey: PublicKey,
remoteIdentifier: RemoteBytes,
remoteKey: PublicKey) throws -> Fingerprint
where LocalBytes: ContiguousBytes, RemoteBytes: ContiguousBytes {
public func create(version: Int,
localIdentifier: [UInt8],
localKey: PublicKey,
remoteIdentifier: [UInt8],
remoteKey: PublicKey) throws -> Fingerprint {
var obj: OpaquePointer?
try localIdentifier.withUnsafeBytes { localBytes in
try remoteIdentifier.withUnsafeBytes { remoteBytes in
try checkError(signal_fingerprint_new(&obj, UInt32(iterations), UInt32(version),
localBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), localBytes.count,
localKey.nativeHandle,
remoteBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), remoteBytes.count,
remoteKey.nativeHandle))
}
}
try checkError(signal_fingerprint_new(&obj, UInt32(iterations), UInt32(version),
localIdentifier, localIdentifier.count,
localKey.nativeHandle,
remoteIdentifier, remoteIdentifier.count,
remoteKey.nativeHandle))
let fprintStr = try invokeFnReturningString {
signal_fingerprint_display_string(obj, $0)

View File

@ -1,5 +1,4 @@
import SignalFfi
import Foundation
public struct IdentityKey: Equatable {
public let publicKey: PublicKey
@ -8,7 +7,7 @@ public struct IdentityKey: Equatable {
self.publicKey = publicKey
}
public init<Bytes: ContiguousBytes>(bytes: Bytes) throws {
public init(bytes: [UInt8]) throws {
publicKey = try PublicKey(bytes)
}
@ -27,12 +26,10 @@ public struct IdentityKeyPair {
return IdentityKeyPair(publicKey: publicKey, privateKey: privateKey)
}
public init<Bytes: ContiguousBytes>(bytes: Bytes) throws {
public init(bytes: [UInt8]) throws {
var pubkeyPtr: OpaquePointer?
var privkeyPtr: OpaquePointer?
try bytes.withUnsafeBytes {
try checkError(signal_identitykeypair_deserialize(&pubkeyPtr, &privkeyPtr, $0.baseAddress?.assumingMemoryBound(to: UInt8.self), $0.count))
}
try checkError(signal_identitykeypair_deserialize(&pubkeyPtr, &privkeyPtr, bytes, bytes.count))
publicKey = PublicKey(owned: pubkeyPtr!)
privateKey = PrivateKey(owned: privkeyPtr!)

View File

@ -1,26 +1,24 @@
import SignalFfi
import Foundation
public func hkdf<InputBytes, SaltBytes, InfoBytes>(outputLength: Int,
version: UInt32,
inputKeyMaterial: InputBytes,
salt: SaltBytes,
info: InfoBytes) throws -> [UInt8]
where InputBytes: ContiguousBytes, SaltBytes: ContiguousBytes, InfoBytes: ContiguousBytes {
public func hkdf(outputLength: Int,
version: UInt32,
inputKeyMaterial: [UInt8],
salt: [UInt8],
info: [UInt8]) throws -> [UInt8] {
var output = Array(repeating: UInt8(0x00), count: outputLength)
try inputKeyMaterial.withUnsafeBytes { inputBytes in
try salt.withUnsafeBytes { saltBytes in
try info.withUnsafeBytes { infoBytes in
try checkError(signal_hkdf_derive(&output,
outputLength,
Int32(version),
inputBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), inputBytes.count,
saltBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), saltBytes.count,
infoBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), infoBytes.count))
}
}
}
let error = signal_hkdf_derive(&output,
outputLength,
Int32(version),
inputKeyMaterial,
inputKeyMaterial.count,
info,
info.count,
salt,
salt.count)
try checkError(error)
return output
}

View File

@ -1,13 +1,9 @@
import SignalFfi
import Foundation
public class PrivateKey: ClonableHandleOwner {
public init<Bytes: ContiguousBytes>(_ bytes: Bytes) throws {
let handle: OpaquePointer? = try bytes.withUnsafeBytes {
var result: OpaquePointer?
try checkError(signal_privatekey_deserialize(&result, $0.baseAddress?.assumingMemoryBound(to: UInt8.self), $0.count))
return result
}
public init(_ bytes: [UInt8]) throws {
var handle: OpaquePointer?
try checkError(signal_privatekey_deserialize(&handle, bytes, bytes.count))
super.init(owned: handle!)
}
@ -35,11 +31,9 @@ public class PrivateKey: ClonableHandleOwner {
}
}
public func generateSignature<Bytes: ContiguousBytes>(message: Bytes) throws -> [UInt8] {
return try message.withUnsafeBytes { messageBytes in
try invokeFnReturningArray {
signal_privatekey_sign($0, $1, nativeHandle, messageBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), messageBytes.count)
}
public func generateSignature(message: [UInt8]) throws -> [UInt8] {
return try invokeFnReturningArray {
signal_privatekey_sign($0, $1, nativeHandle, message, message.count)
}
}

View File

@ -1,5 +1,4 @@
import SignalFfi
import Foundation
/*
SignalFfiError *signal_process_prekey_bundle(PreKeyBundle *bundle,
@ -37,17 +36,15 @@ SignalFfiError *signal_decrypt_pre_key_message(const unsigned char **result,
*/
public func signalEncrypt<Bytes: ContiguousBytes>(message: Bytes,
for address: ProtocolAddress,
sessionStore: SessionStore,
identityStore: IdentityKeyStore,
context: UnsafeMutableRawPointer?) throws -> CiphertextMessage {
return try message.withUnsafeBytes { messageBytes in
try withSessionStore(sessionStore) { ffiSessionStore in
try withIdentityKeyStore(identityStore) { ffiIdentityStore in
try invokeFnReturningCiphertextMessage {
signal_encrypt_message($0, messageBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), messageBytes.count, address.nativeHandle, ffiSessionStore, ffiIdentityStore, context)
}
public func signalEncrypt(message: [UInt8],
for address: ProtocolAddress,
sessionStore: SessionStore,
identityStore: IdentityKeyStore,
context: UnsafeMutableRawPointer?) throws -> CiphertextMessage {
return try withSessionStore(sessionStore) { ffiSessionStore in
try withIdentityKeyStore(identityStore) { ffiIdentityStore in
try invokeFnReturningCiphertextMessage {
signal_encrypt_message($0, message, message.count, address.nativeHandle, ffiSessionStore, ffiIdentityStore, context)
}
}
}
@ -99,28 +96,24 @@ public func processPreKeyBundle(_ bundle: PreKeyBundle,
}
}
public func groupEncrypt<Bytes: ContiguousBytes>(groupId: SenderKeyName,
message: Bytes,
store: SenderKeyStore,
context: UnsafeMutableRawPointer?) throws -> [UInt8] {
return try message.withUnsafeBytes { messageBytes in
return try withSenderKeyStore(store) { ffiStore in
return try invokeFnReturningArray {
signal_group_encrypt_message($0, $1, groupId.nativeHandle, messageBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), messageBytes.count, ffiStore, context)
}
public func groupEncrypt(groupId: SenderKeyName,
message: [UInt8],
store: SenderKeyStore,
context: UnsafeMutableRawPointer?) throws -> [UInt8] {
return try withSenderKeyStore(store) { ffiStore in
return try invokeFnReturningArray {
signal_group_encrypt_message($0, $1, groupId.nativeHandle, message, message.count, ffiStore, context)
}
}
}
public func groupDecrypt<Bytes: ContiguousBytes>(groupId: SenderKeyName,
message: Bytes,
store: SenderKeyStore,
context: UnsafeMutableRawPointer?) throws -> [UInt8] {
return try message.withUnsafeBytes { messageBytes in
return try withSenderKeyStore(store) { ffiStore in
return try invokeFnReturningArray {
signal_group_decrypt_message($0, $1, groupId.nativeHandle, messageBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), messageBytes.count, ffiStore, context)
}
public func groupDecrypt(groupId: SenderKeyName,
message: [UInt8],
store: SenderKeyStore,
context: UnsafeMutableRawPointer?) throws -> [UInt8] {
return try withSenderKeyStore(store) { ffiStore in
return try invokeFnReturningArray {
signal_group_decrypt_message($0, $1, groupId.nativeHandle, message, message.count, ffiStore, context)
}
}
}

View File

@ -1,13 +1,9 @@
import SignalFfi
import Foundation
public class PublicKey: ClonableHandleOwner {
public init<Bytes: ContiguousBytes>(_ bytes: Bytes) throws {
let handle: OpaquePointer? = try bytes.withUnsafeBytes {
var result: OpaquePointer?
try checkError(signal_publickey_deserialize(&result, $0.baseAddress?.assumingMemoryBound(to: UInt8.self), $0.count))
return result
}
public init(_ bytes: [UInt8]) throws {
var handle: OpaquePointer?
try checkError(signal_publickey_deserialize(&handle, bytes, bytes.count))
super.init(owned: handle!)
}
@ -33,14 +29,9 @@ public class PublicKey: ClonableHandleOwner {
}
}
public func verifySignature<MessageBytes, SignatureBytes>(message: MessageBytes, signature: SignatureBytes) throws -> Bool
where MessageBytes: ContiguousBytes, SignatureBytes: ContiguousBytes {
public func verifySignature(message: [UInt8], signature: [UInt8]) throws -> Bool {
var result: Bool = false
try message.withUnsafeBytes { messageBytes in
try signature.withUnsafeBytes { signatureBytes in
try checkError(signal_publickey_verify(nativeHandle, &result, messageBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), messageBytes.count, signatureBytes.baseAddress?.assumingMemoryBound(to: UInt8.self), signatureBytes.count))
}
}
try checkError(signal_publickey_verify(nativeHandle, &result, message, message.count, signature, signature.count))
return result
}

View File

@ -1,5 +1,4 @@
import SignalFfi
import Foundation
public class PreKeySignalMessage {
private var handle: OpaquePointer?
@ -8,12 +7,8 @@ public class PreKeySignalMessage {
signal_pre_key_signal_message_destroy(handle)
}
public init<Bytes: ContiguousBytes>(bytes: Bytes) throws {
handle = try bytes.withUnsafeBytes {
var result: OpaquePointer?
try checkError(signal_pre_key_signal_message_deserialize(&result, $0.baseAddress?.assumingMemoryBound(to: UInt8.self), $0.count))
return result
}
public init(bytes: [UInt8]) throws {
try checkError(signal_pre_key_signal_message_deserialize(&handle, bytes, bytes.count))
}
public init(version: UInt8,

View File

@ -1,5 +1,4 @@
import SignalFfi
import Foundation
public class SenderKeyDistributionMessage {
private var handle: OpaquePointer?
@ -19,20 +18,17 @@ public class SenderKeyDistributionMessage {
}
}
public init<Bytes: ContiguousBytes>(keyId: UInt32,
iteration: UInt32,
chainKey: Bytes,
publicKey: PublicKey) throws {
handle = try chainKey.withUnsafeBytes {
var result: OpaquePointer?
try checkError(signal_sender_key_distribution_message_new(&result,
keyId,
iteration,
$0.baseAddress?.assumingMemoryBound(to: UInt8.self),
$0.count,
publicKey.nativeHandle))
return result
}
public init(keyId: UInt32,
iteration: UInt32,
chainKey: [UInt8],
publicKey: PublicKey) throws {
try checkError(signal_sender_key_distribution_message_new(&handle,
keyId,
iteration,
chainKey,
chainKey.count,
publicKey.nativeHandle))
}
public init(bytes: [UInt8]) throws {

View File

@ -1,5 +1,4 @@
import SignalFfi
import Foundation
public class SenderKeyMessage {
private var handle: OpaquePointer?
@ -8,28 +7,21 @@ public class SenderKeyMessage {
signal_sender_key_message_destroy(handle)
}
public init<Bytes: ContiguousBytes>(keyId: UInt32,
iteration: UInt32,
ciphertext: Bytes,
privateKey: PrivateKey) throws {
handle = try ciphertext.withUnsafeBytes {
var result: OpaquePointer?
try checkError(signal_sender_key_message_new(&result,
keyId,
iteration,
$0.baseAddress?.assumingMemoryBound(to: UInt8.self),
$0.count,
privateKey.nativeHandle))
return result
}
public init(keyId: UInt32,
iteration: UInt32,
ciphertext: [UInt8],
privateKey: PrivateKey) throws {
try checkError(signal_sender_key_message_new(&handle,
keyId,
iteration,
ciphertext,
ciphertext.count,
privateKey.nativeHandle))
}
public init<Bytes: ContiguousBytes>(bytes: Bytes) throws {
handle = try bytes.withUnsafeBytes {
var result: OpaquePointer?
try checkError(signal_sender_key_message_deserialize(&result, $0.baseAddress?.assumingMemoryBound(to: UInt8.self), $0.count))
return result
}
public init(bytes: [UInt8]) throws {
try checkError(signal_sender_key_message_deserialize(&handle, bytes, bytes.count))
}
public func keyId() throws -> UInt32 {

View File

@ -1,5 +1,4 @@
import SignalFfi
import Foundation
public class SignalMessage {
private var handle: OpaquePointer?
@ -12,40 +11,29 @@ public class SignalMessage {
handle = rawPtr
}
public init<Bytes: ContiguousBytes>(bytes: Bytes) throws {
handle = try bytes.withUnsafeBytes {
var result: OpaquePointer?
try checkError(signal_message_deserialize(&result, $0.baseAddress?.assumingMemoryBound(to: UInt8.self), $0.count))
return result
}
public init(bytes: [UInt8]) throws {
try checkError(signal_message_deserialize(&handle, bytes, bytes.count))
}
public init<MacBytes, CiphertextBytes>(version: UInt8,
macKey: MacBytes,
senderRatchetKey: PublicKey,
counter: UInt32,
previousCounter: UInt32,
ciphertext: CiphertextBytes,
sender senderIdentityKey: PublicKey,
receiver receiverIdentityKey: PublicKey) throws
where MacBytes: ContiguousBytes, CiphertextBytes: ContiguousBytes {
handle = try macKey.withUnsafeBytes { macBytes in
try ciphertext.withUnsafeBytes { ciphertextBytes in
var result: OpaquePointer?
try checkError(signal_message_new(&result,
version,
macBytes.baseAddress?.assumingMemoryBound(to: UInt8.self),
macBytes.count,
senderRatchetKey.nativeHandle,
counter,
previousCounter,
ciphertextBytes.baseAddress?.assumingMemoryBound(to: UInt8.self),
ciphertextBytes.count,
senderIdentityKey.nativeHandle,
receiverIdentityKey.nativeHandle))
return result
}
}
public init(version: UInt8,
macKey: [UInt8],
senderRatchetKey: PublicKey,
counter: UInt32,
previousCounter: UInt32,
ciphertext: [UInt8],
sender senderIdentityKey: PublicKey,
receiver receiverIdentityKey: PublicKey) throws {
try checkError(signal_message_new(&handle,
version,
macKey,
macKey.count,
senderRatchetKey.nativeHandle,
counter,
previousCounter,
ciphertext,
ciphertext.count,
senderIdentityKey.nativeHandle,
receiverIdentityKey.nativeHandle))
}
public func senderRatchetKey() throws -> PublicKey {
@ -78,19 +66,17 @@ public class SignalMessage {
}
}
public func verifyMac<Bytes: ContiguousBytes>(sender: PublicKey,
receiver: PublicKey,
macKey: Bytes) throws -> Bool {
return try macKey.withUnsafeBytes {
var result: Bool = false
try checkError(signal_message_verify_mac(&result,
handle,
sender.nativeHandle,
receiver.nativeHandle,
$0.baseAddress?.assumingMemoryBound(to: UInt8.self),
$0.count))
return result
}
public func verifyMac(sender: PublicKey,
receiver: PublicKey,
macKey: [UInt8]) throws -> Bool {
var result: Bool = false
try checkError(signal_message_verify_mac(&result,
handle,
sender.nativeHandle,
receiver.nativeHandle,
macKey,
macKey.count))
return result
}
internal var nativeHandle: OpaquePointer? {

View File

@ -1,5 +1,4 @@
import SignalFfi
import Foundation
public class PreKeyBundle {
private var handle: OpaquePointer?
@ -13,52 +12,46 @@ public class PreKeyBundle {
}
// with a prekey
public init<Bytes: ContiguousBytes>(registrationId: UInt32,
deviceId: UInt32,
prekeyId: UInt32,
prekey: PublicKey,
signedPrekeyId: UInt32,
signedPrekey: PublicKey,
signedPrekeySignature: Bytes,
identity identityKey: IdentityKey) throws {
handle = try signedPrekeySignature.withUnsafeBytes {
var prekeyId = prekeyId
var result: OpaquePointer?
try checkError(signal_pre_key_bundle_new(&result,
registrationId,
deviceId,
&prekeyId,
prekey.nativeHandle,
signedPrekeyId,
signedPrekey.nativeHandle,
$0.baseAddress?.assumingMemoryBound(to: UInt8.self),
$0.count,
identityKey.publicKey.nativeHandle))
return result
}
public init(registrationId: UInt32,
deviceId: UInt32,
prekeyId: UInt32,
prekey: PublicKey,
signedPrekeyId: UInt32,
signedPrekey: PublicKey,
signedPrekeySignature: [UInt8],
identity identityKey: IdentityKey) throws {
var prekeyId = prekeyId
try checkError(signal_pre_key_bundle_new(&handle,
registrationId,
deviceId,
&prekeyId,
prekey.nativeHandle,
signedPrekeyId,
signedPrekey.nativeHandle,
signedPrekeySignature,
signedPrekeySignature.count,
identityKey.publicKey.nativeHandle))
}
// without a prekey
public init<Bytes: ContiguousBytes>(registrationId: UInt32,
deviceId: UInt32,
signedPrekeyId: UInt32,
signedPrekey: PublicKey,
signedPrekeySignature: Bytes,
identity identityKey: IdentityKey) throws {
handle = try signedPrekeySignature.withUnsafeBytes {
var result: OpaquePointer?
try checkError(signal_pre_key_bundle_new(&result,
registrationId,
deviceId,
nil,
nil,
signedPrekeyId,
signedPrekey.nativeHandle,
$0.baseAddress?.assumingMemoryBound(to: UInt8.self),
$0.count,
identityKey.publicKey.nativeHandle))
return result
}
public init(registrationId: UInt32,
deviceId: UInt32,
signedPrekeyId: UInt32,
signedPrekey: PublicKey,
signedPrekeySignature: [UInt8],
identity identityKey: IdentityKey) throws {
try checkError(signal_pre_key_bundle_new(&handle,
registrationId,
deviceId,
nil,
nil,
signedPrekeyId,
signedPrekey.nativeHandle,
signedPrekeySignature,
signedPrekeySignature.count,
identityKey.publicKey.nativeHandle))
}
public func registrationId() throws -> UInt32 {

View File

@ -1,7 +1,8 @@
import SignalFfi
import Foundation
public class PreKeyRecord: ClonableHandleOwner {
private var handle: OpaquePointer?
internal override class func destroyNativeHandle(_ handle: OpaquePointer) {
signal_pre_key_record_destroy(handle)
}
@ -10,12 +11,9 @@ public class PreKeyRecord: ClonableHandleOwner {
return signal_pre_key_record_clone(&newHandle, currentHandle)
}
public init<Bytes: ContiguousBytes>(bytes: Bytes) throws {
let handle: OpaquePointer? = try bytes.withUnsafeBytes {
var result: OpaquePointer?
try checkError(signal_pre_key_record_deserialize(&result, $0.baseAddress?.assumingMemoryBound(to: UInt8.self), $0.count))
return result
}
public init(bytes: [UInt8]) throws {
var handle: OpaquePointer?
try checkError(signal_pre_key_record_deserialize(&handle, bytes, bytes.count))
super.init(owned: handle!)
}
@ -40,25 +38,25 @@ public class PreKeyRecord: ClonableHandleOwner {
public func serialize() throws -> [UInt8] {
return try invokeFnReturningArray {
signal_pre_key_record_serialize(nativeHandle, $0, $1)
signal_pre_key_record_serialize(handle, $0, $1)
}
}
public func id() throws -> UInt32 {
return try invokeFnReturningInteger {
signal_pre_key_record_get_id(nativeHandle, $0)
signal_pre_key_record_get_id(handle, $0)
}
}
public func publicKey() throws -> PublicKey {
return try invokeFnReturningPublicKey {
signal_pre_key_record_get_public_key($0, nativeHandle)
signal_pre_key_record_get_public_key($0, handle)
}
}
public func privateKey() throws -> PrivateKey {
return try invokeFnReturningPrivateKey {
signal_pre_key_record_get_private_key($0, nativeHandle)
signal_pre_key_record_get_private_key($0, handle)
}
}
}

View File

@ -1,5 +1,4 @@
import SignalFfi
import Foundation
public class SenderKeyRecord: ClonableHandleOwner {
internal override class func destroyNativeHandle(_ handle: OpaquePointer) {
@ -12,12 +11,9 @@ public class SenderKeyRecord: ClonableHandleOwner {
private var handle: OpaquePointer?
public init<Bytes: ContiguousBytes>(bytes: Bytes) throws {
let handle: OpaquePointer? = try bytes.withUnsafeBytes {
var result: OpaquePointer?
try checkError(signal_sender_key_record_deserialize(&result, $0.baseAddress?.assumingMemoryBound(to: UInt8.self), $0.count))
return result
}
public init(bytes: [UInt8]) throws {
var handle: OpaquePointer?
try checkError(signal_sender_key_record_deserialize(&handle, bytes, bytes.count))
super.init(owned: handle!)
}

View File

@ -1,5 +1,4 @@
import SignalFfi
import Foundation
public class SessionRecord: ClonableHandleOwner {
internal override class func destroyNativeHandle(_ handle: OpaquePointer) {
@ -10,12 +9,9 @@ public class SessionRecord: ClonableHandleOwner {
return signal_session_record_clone(&newHandle, currentHandle)
}
public init<Bytes: ContiguousBytes>(bytes: Bytes) throws {
let handle: OpaquePointer? = try bytes.withUnsafeBytes {
var result: OpaquePointer?
try checkError(signal_session_record_deserialize(&result, $0.baseAddress?.assumingMemoryBound(to: UInt8.self), $0.count))
return result
}
public init(bytes: [UInt8]) throws {
var handle: OpaquePointer?
try checkError(signal_session_record_deserialize(&handle, bytes, bytes.count))
super.init(owned: handle!)
}

View File

@ -1,5 +1,4 @@
import SignalFfi
import Foundation
public class SignedPreKeyRecord: ClonableHandleOwner {
internal override class func destroyNativeHandle(_ handle: OpaquePointer) {
@ -10,27 +9,21 @@ public class SignedPreKeyRecord: ClonableHandleOwner {
return signal_signed_pre_key_record_clone(&newHandle, currentHandle)
}
public init<Bytes: ContiguousBytes>(bytes: Bytes) throws {
let handle: OpaquePointer? = try bytes.withUnsafeBytes {
var result: OpaquePointer?
try checkError(signal_signed_pre_key_record_deserialize(&result, $0.baseAddress?.assumingMemoryBound(to: UInt8.self), $0.count))
return result
}
public init(bytes: [UInt8]) throws {
var handle: OpaquePointer?
try checkError(signal_signed_pre_key_record_deserialize(&handle, bytes, bytes.count))
super.init(owned: handle!)
}
public init<Bytes: ContiguousBytes>(id: UInt32,
timestamp: UInt64,
privateKey: PrivateKey,
signature: Bytes) throws {
public init(id: UInt32,
timestamp: UInt64,
privateKey: PrivateKey,
signature: [UInt8]) throws {
let publicKey = try privateKey.publicKey()
let handle: OpaquePointer? = try signature.withUnsafeBytes {
var result: OpaquePointer?
try checkError(signal_signed_pre_key_record_new(&result, id, timestamp,
publicKey.nativeHandle, privateKey.nativeHandle,
$0.baseAddress?.assumingMemoryBound(to: UInt8.self), $0.count))
return result
}
var handle: OpaquePointer?
try checkError(signal_signed_pre_key_record_new(&handle, id, timestamp,
publicKey.nativeHandle, privateKey.nativeHandle,
signature, signature.count))
super.init(owned: handle!)
}

View File

@ -2,14 +2,36 @@ import XCTest
import SignalProtocol
class PublicAPITests: XCTestCase {
func testHkdfSimple() {
func testHkdf() {
let ikm: [UInt8] = [
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
]
let info: [UInt8] = []
let salt: [UInt8] = []
let okm: [UInt8] = [0x8d, 0xa4, 0xe7, 0x75]
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
];
let info: [UInt8] = [
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
];
let salt: [UInt8] = [
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf
];
let okm: [UInt8] = [
0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34,
0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c,
0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09,
0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71,
0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f,
0x1d, 0x87];
let version = UInt32(3)
let derived = try! hkdf(outputLength: okm.count,
@ -22,29 +44,8 @@ class PublicAPITests: XCTestCase {
XCTAssertThrowsError(try hkdf(outputLength: okm.count,
version: 19,
inputKeyMaterial: ikm,
salt: salt,
info: info))
}
func testHkdfUsingRFCExample() {
// https://tools.ietf.org/html/rfc5869 A.2
let ikm: [UInt8] = Array(0...0x4f)
let salt: [UInt8] = Array(0x60...0xaf)
let info: [UInt8] = Array(0xb0...0xff)
let okm: [UInt8] = [0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34,
0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c,
0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09,
0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71,
0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f,
0x1d, 0x87]
let version = UInt32(3)
let derived = try! hkdf(outputLength: okm.count,
version: version,
inputKeyMaterial: ikm,
salt: salt,
info: info)
XCTAssertEqual(derived, okm)
salt: salt,
info: info))
}
func testAddress() {
@ -317,13 +318,12 @@ class PublicAPITests: XCTestCase {
static var allTests: [(String, (PublicAPITests) -> () throws -> Void)] {
return [
("testAddreses", testAddress),
("testFingerprint", testFingerprint),
("testPkOperations", testPkOperations),
("testHkdfSimple", testHkdfSimple),
("testHkdfUsingRFCExample", testHkdfUsingRFCExample),
("testGroupCipher", testGroupCipher),
("testSessionCipher", testSessionCipher),
("testAddreses", testAddress),
("testFingerprint", testFingerprint),
("testPkOperations", testPkOperations),
("testHkdf", testHkdf),
("testGroupCipher", testGroupCipher),
("testSessionCipher", testSessionCipher),
]
}
}