Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
firefox-merge-…
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
executable file 258 lines (224 sloc) 11.5 KB
/* 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)
}
}
}