mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-22 08:27:31 +09:00
Dactyloidae iOS initial commit
This commit is contained in:
parent
daa6179d22
commit
7154a0497e
2123 changed files with 197052 additions and 0 deletions
258
mobile/ios/PushTests/PushCryptoTests.swift
Normal file
258
mobile/ios/PushTests/PushCryptoTests.swift
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
@testable import Account
|
||||
import XCTest
|
||||
|
||||
class PushCryptoTests: XCTestCase {
|
||||
|
||||
let push = PushCrypto.sharedInstance
|
||||
|
||||
func testRoundtrip_base64urlSafe() {
|
||||
let ogString = "I am the walrus! I am the eggman!"
|
||||
let ogData = ogString.data(using: .utf8)!
|
||||
|
||||
guard let encodedString = ogData.base64urlSafeEncodedString else {
|
||||
return XCTFail("base64urlSafeEncodedString failed")
|
||||
}
|
||||
|
||||
guard let decodedData = encodedString.base64urlSafeDecodedData else {
|
||||
return XCTFail("base64urlSafeDecodedData failed")
|
||||
}
|
||||
|
||||
guard let decodedString = decodedData.utf8EncodedString else {
|
||||
return XCTFail("utf8EncodedString failed")
|
||||
}
|
||||
|
||||
XCTAssertEqual(decodedString, ogString)
|
||||
}
|
||||
|
||||
func testRoundtrip_base64urlSafe_withSpecialChars() {
|
||||
let encoded = "mW-ti1CqLQK4PyZBKy4q7g"
|
||||
|
||||
XCTAssertEqual(encoded.base64urlSafeDecodedData!.base64urlSafeEncodedString, encoded)
|
||||
}
|
||||
|
||||
struct Aes128GcmTest {
|
||||
let payload: String
|
||||
let recvPrivKey: String
|
||||
let authSecret: String
|
||||
let plaintext: String
|
||||
}
|
||||
|
||||
func testDecrypt_aes128gcm() {
|
||||
let tests = [
|
||||
Aes128GcmTest(
|
||||
payload: "SVzmyN6TpFOehi6GNJk8uwAAABhBBDwzeKLAq5VOFJhxjoXwi7cj-30l4TWmY_44WITrgZIza_kKVO1yDxwEXAtAXpu8OiFCsWyJCGc0w3Trr3CZ5kJ-LTLIraUBhwPFSxC0geECfXIJ2Ma0NVP6Ezr6WX8t3EWluoFAlE5kkLuNbZm6HQLmDZX0jOZER3wXIx2VuXpPld0",
|
||||
recvPrivKey: "yJnRHTLit-b-dJh4b1DyO5is5Tl60mHeObpkSezBLK0",
|
||||
authSecret: "mW-ti1CqLQK4PyZBKy4q7g",
|
||||
plaintext: "I am the walrus"
|
||||
),
|
||||
Aes128GcmTest(
|
||||
payload: "DGv6ra1nlYgDCS1FRnbzlwAAEABBBP4z9KsN6nGRTbVYI_c7VJSPQTBtkgcy27mlmlMoZIIgDll6e3vCYLocInmYWAmS6TlzAC8wEqKK6PBru3jl7A_yl95bQpu6cVPTpK4Mqgkf1CXztLVBSt2Ks3oZwbuwXPXLWyouBWLVWGNWQexSgSxsj_Qulcy4a-fN",
|
||||
recvPrivKey: "q1dXpw3UpT5VOmu_cf_v6ih07Aems3njxI-JWgLcM94",
|
||||
authSecret: "BTBZMqHH6r4Tts7J_aSIgg",
|
||||
plaintext: "When I grow up, I want to be a watermelon"
|
||||
),
|
||||
]
|
||||
|
||||
for test in tests {
|
||||
if let deciphered = try? push.aes128gcm(payload: test.payload,
|
||||
decryptWith: test.recvPrivKey,
|
||||
authenticateWith: test.authSecret) {
|
||||
XCTAssertEqual(deciphered, test.plaintext)
|
||||
} else {
|
||||
XCTFail("Failed to decipher \(test.plaintext)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testFail_aes128gcm() {
|
||||
let tests = [
|
||||
Aes128GcmTest(
|
||||
payload: "bad base 64 encoding",
|
||||
recvPrivKey: "yJnRHTLit-b-dJh4b1DyO5is5Tl60mHeObpkSezBLK0",
|
||||
authSecret: "mW-ti1CqLQK4PyZBKy4q7g",
|
||||
plaintext: "bad base64"
|
||||
),
|
||||
Aes128GcmTest(
|
||||
payload: "DGv6ra1nlYgDCS1FRnbzlwAAEABBBP4z9KsN6nGRTbVYI_c7VJSPQTBtkgcy27mlmlMoZIIgDll6e3vCYLocInmYWAmS6TlzAC8wEqKK6PBru3jl7A_yl95bQpu6cVPTpK4Mqgkf1CXztLVBSt2Ks3oZwbuwXPXLWyouBWLVWGNWQexSgSxsj_Qulcy4a-fN",
|
||||
recvPrivKey: "badkey",
|
||||
authSecret: "BTBZMqHH6r4Tts7J_aSIgg",
|
||||
plaintext: "bad key"
|
||||
),
|
||||
]
|
||||
|
||||
for test in tests {
|
||||
do {
|
||||
_ = try push.aes128gcm(payload: test.payload,
|
||||
decryptWith: test.recvPrivKey,
|
||||
authenticateWith: test.authSecret)
|
||||
|
||||
XCTFail("Somehow, deciphered \(test.plaintext)")
|
||||
} catch PushCryptoError.base64DecodeError {
|
||||
XCTAssertEqual(test.plaintext, tests[0].plaintext)
|
||||
} catch PushCryptoError.decryptionError(_) {
|
||||
XCTAssertEqual(test.plaintext, tests[1].plaintext)
|
||||
} catch PushCryptoError.utf8EncodingError {
|
||||
XCTFail("Not tested")
|
||||
} catch {
|
||||
XCTFail("Not tested but found \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testRoundTrip_aes128gcm() {
|
||||
// The real reason for this test is to test generateKeys()
|
||||
guard let keys = try? push.generateKeys() else {
|
||||
return XCTFail("Generating keys should not fail")
|
||||
}
|
||||
|
||||
let plaintext = "I am the egg man!"
|
||||
|
||||
guard let payload = try? push.aes128gcm(plaintext: plaintext, encryptWith: keys.p256dhPublicKey, authenticateWith: keys.auth, rs: 1024, padLen: 2) else {
|
||||
return XCTFail("Encryption should not fail")
|
||||
}
|
||||
|
||||
guard let deciphered = try? push.aes128gcm(payload: payload, decryptWith: keys.p256dhPrivateKey, authenticateWith: keys.auth) else {
|
||||
return XCTFail("Decryption should not fail")
|
||||
}
|
||||
|
||||
XCTAssertEqual(deciphered, plaintext)
|
||||
}
|
||||
|
||||
struct AesGcmTest {
|
||||
let plaintext: String
|
||||
let recvPrivKey: String
|
||||
let authSecret: String
|
||||
let ciphertext: String
|
||||
let cryptoKey: String
|
||||
let encryption: String
|
||||
}
|
||||
|
||||
func testDecrypt_aesgcm() {
|
||||
let tests = [
|
||||
AesGcmTest(
|
||||
plaintext: "I am the walrus",
|
||||
recvPrivKey: "9FWl15_QUQAWDaD3k3l50ZBZQJ4au27F1V4F0uLSD_M",
|
||||
authSecret: "R29vIGdvbyBnJyBqb29iIQ",
|
||||
ciphertext: "6nqAQUME8hNqw5J3kl8cpVVJylXKYqZOeseZG8UueKpA",
|
||||
cryptoKey: "keyid=\"dhkey\"; dh=\"BNoRDbb84JGm8g5Z5CFxurSqsXWJ11ItfXEWYVLE85Y7CYkDjXsIEc4aqxYaQ1G8BqkXCJ6DPpDrWtdWj_mugHU\"",
|
||||
encryption: "keyid=\"dhkey\"; salt=\"lngarbyKfMoi9Z75xYXmkg\""
|
||||
),
|
||||
AesGcmTest(
|
||||
plaintext: "Small record size",
|
||||
recvPrivKey: "4h23G_KkXC9TvBSK2v0Q7ImpS2YAuRd8hQyN0rFAwBg",
|
||||
authSecret: "g2rWVHUCpUxgcL9Tz7vyeQ",
|
||||
ciphertext: "oY4e5eDatDVt2fpQylxbPJM-3vrfhDasfPc8Q1PWt4tPfMVbz_sDNL_cvr0DXXkdFzS1lxsJsj550USx4MMl01ihjImXCjrw9R5xFgFrCAqJD3GwXA1vzS4T5yvGVbUp3SndMDdT1OCcEofTn7VC6xZ-zP8rzSQfDCBBxmPU7OISzr8Z4HyzFCGJeBfqiZ7yUfNlKF1x5UaZ4X6iU_TXx5KlQy_toV1dXZ2eEAMHJUcSdArvB6zRpFdEIxdcHcJyo1BIYgAYTDdAIy__IJVCPY_b2CE5W_6ohlYKB7xDyH8giNuWWXAgBozUfScLUVjPC38yJTpAUi6w6pXgXUWffende5FreQpnMFL1L4G-38wsI_-ISIOzdO8QIrXHxmtc1S5xzYu8bMqSgCinvCEwdeGFCmighRjj8t1zRWo0D14rHbQLPR_b1P5SvEeJTtS9Nm3iibM",
|
||||
cryptoKey: "dh=BCg6ZIGuE2ZNm2ti6Arf4CDVD_8--aLXAGLYhpghwjl1xxVjTLLpb7zihuEOGGbyt8Qj0_fYHBP4ObxwJNl56bk",
|
||||
encryption: "salt=5LIDBXbvkBvvb7ZdD-T4PQ; rs=3"
|
||||
),
|
||||
AesGcmTest(
|
||||
plaintext: "Yet another message",
|
||||
recvPrivKey: "4h23G_KkXC9TvBSK2v0Q7ImpS2YAuRd8hQyN0rFAwBg",
|
||||
authSecret: "6plwZnSpVUbF7APDXus3UQ",
|
||||
ciphertext: "uEC5B_tR-fuQ3delQcrzrDCp40W6ipMZjGZ78USDJ5sMj-6bAOVG3AK6JqFl9E6AoWiBYYvMZfwThVxmDnw6RHtVeLKFM5DWgl1EwkOohwH2EhiDD0gM3io-d79WKzOPZE9rDWUSv64JstImSfX_ADQfABrvbZkeaWxh53EG59QMOElFJqHue4dMURpsMXg",
|
||||
cryptoKey: "dh=BEaA4gzA3i0JDuirGhiLgymS4hfFX7TNTdEhSk_HBlLpkjgCpjPL5c-GL9uBGIfa_fhGNKKFhXz1k9Kyens2ZpQ",
|
||||
encryption: "salt=ZFhzj0S-n29g9P2p4-I7tA; rs=8"
|
||||
),
|
||||
AesGcmTest(
|
||||
plaintext: "Some message",
|
||||
recvPrivKey: "4h23G_KkXC9TvBSK2v0Q7ImpS2YAuRd8hQyN0rFAwBg",
|
||||
authSecret: "aTDc6JebzR6eScy2oLo4RQ",
|
||||
ciphertext: "Oo34w2F9VVnTMFfKtdx48AZWQ9Li9M6DauWJVgXU",
|
||||
cryptoKey: "dh=BCHFVrflyxibGLlgztLwKelsRZp4gqX3tNfAKFaxAcBhpvYeN1yIUMrxaDKiLh4LNKPtj0BOXGdr-IQ-QP82Wjo",
|
||||
encryption: "salt=zCU18Rw3A5aB_Xi-vfixmA; rs=24"
|
||||
)
|
||||
]
|
||||
|
||||
for test in tests {
|
||||
if let deciphered = try? push.aesgcm(ciphertext: test.ciphertext,
|
||||
withHeaders: PushCryptoHeaders(encryption: test.encryption, cryptoKey: test.cryptoKey),
|
||||
decryptWith: test.recvPrivKey,
|
||||
authenticateWith: test.authSecret) {
|
||||
XCTAssertEqual(deciphered, test.plaintext)
|
||||
} else {
|
||||
XCTFail("Failed to decipher \(test.plaintext)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testFail_aesgcm() {
|
||||
let tests = [
|
||||
AesGcmTest(
|
||||
plaintext: "bad base64",
|
||||
recvPrivKey: "4h23G_KkXC9TvBSK2v0Q7ImpS2YAuRd8hQyN0rFAwBg",
|
||||
authSecret: "aTDc6JebzR6eScy2oLo4RQ",
|
||||
ciphertext: "non base64",
|
||||
cryptoKey: "dh=BCHFVrflyxibGLlgztLwKelsRZp4gqX3tNfAKFaxAcBhpvYeN1yIUMrxaDKiLh4LNKPtj0BOXGdr-IQ-QP82Wjo",
|
||||
encryption: "salt=zCU18Rw3A5aB_Xi-vfixmA; rs=24"
|
||||
),
|
||||
|
||||
AesGcmTest(
|
||||
plaintext: "bad key",
|
||||
recvPrivKey: "badkey",
|
||||
authSecret: "aTDc6JebzR6eScy2oLo4RQ",
|
||||
ciphertext: "Oo34w2F9VVnTMFfKtdx48AZWQ9Li9M6DauWJVgXU",
|
||||
cryptoKey: "dh=BCHFVrflyxibGLlgztLwKelsRZp4gqX3tNfAKFaxAcBhpvYeN1yIUMrxaDKiLh4LNKPtj0BOXGdr-IQ-QP82Wjo",
|
||||
encryption: "salt=zCU18Rw3A5aB_Xi-vfixmA; rs=24"
|
||||
),
|
||||
]
|
||||
|
||||
for test in tests {
|
||||
do {
|
||||
_ = try push.aesgcm(ciphertext: test.ciphertext,
|
||||
withHeaders: PushCryptoHeaders(encryption: test.encryption, cryptoKey: test.cryptoKey),
|
||||
decryptWith: test.recvPrivKey,
|
||||
authenticateWith: test.authSecret)
|
||||
|
||||
XCTFail("Somehow, deciphered \(test.plaintext)")
|
||||
} catch PushCryptoError.base64DecodeError {
|
||||
XCTAssertEqual(test.plaintext, tests[0].plaintext)
|
||||
} catch PushCryptoError.decryptionError(_) {
|
||||
XCTAssertEqual(test.plaintext, tests[1].plaintext)
|
||||
} catch PushCryptoError.utf8EncodingError {
|
||||
XCTFail("Not tested")
|
||||
} catch {
|
||||
XCTFail("Not tested but found \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testRoundTrip_aesgcm() {
|
||||
guard let keys = try? push.generateKeys() else {
|
||||
return XCTFail("Generating keys should not fail")
|
||||
}
|
||||
|
||||
let plaintext = "While I'm away, I'll write home every day"
|
||||
|
||||
guard let (headers, ciphertext) = try? push.aesgcm(plaintext: plaintext,
|
||||
encryptWith: keys.p256dhPublicKey,
|
||||
authenticateWith: keys.auth,
|
||||
rs: 28,
|
||||
padLen: 16) else {
|
||||
return XCTFail("Encryption should not fail")
|
||||
}
|
||||
|
||||
guard let deciphered = try? push.aesgcm(ciphertext: ciphertext,
|
||||
withHeaders: headers,
|
||||
decryptWith: keys.p256dhPrivateKey,
|
||||
authenticateWith: keys.auth) else {
|
||||
return XCTFail("Decryption should not fail")
|
||||
}
|
||||
|
||||
XCTAssertEqual(deciphered, plaintext)
|
||||
}
|
||||
|
||||
func testKeyGeneration() {
|
||||
guard let keys = try? push.generateKeys() else {
|
||||
return XCTFail("Keys can't be tested")
|
||||
}
|
||||
// We can't really test if the keys are random enough, but we can check if they
|
||||
// roundtrip with the base64urlSafe encoding.
|
||||
for string in [keys.p256dhPublicKey, keys.p256dhPrivateKey, keys.auth] {
|
||||
XCTAssertEqual(string.base64urlSafeDecodedData?.base64urlSafeEncodedString, string)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue