From b8a23a25a3831db2b49795eeab892e71df3b233c Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Sat, 23 Sep 2017 20:48:12 +0200 Subject: [PATCH] Add SecretStream to the OSX target, fix examples --- Examples/CommonCode/Helpers.swift | 2 +- Examples/OSX/AppDelegate.swift | 24 ++---- Examples/OSX/Info.plist | 2 +- Examples/iOS/AppDelegate.swift | 24 ++---- Examples/iOS/ViewController.swift | 21 ++--- Sodium.xcodeproj/project.pbxproj | 10 ++- SodiumTests/ReadmeTests.swift | 94 ++++++++++----------- SodiumTests/SodiumTests.swift | 132 +++++++++++++++--------------- 8 files changed, 144 insertions(+), 165 deletions(-) diff --git a/Examples/CommonCode/Helpers.swift b/Examples/CommonCode/Helpers.swift index db93529..ab7adeb 100644 --- a/Examples/CommonCode/Helpers.swift +++ b/Examples/CommonCode/Helpers.swift @@ -16,7 +16,7 @@ extension Data { func toString() -> String? { return String(data: self, encoding: .utf8) } - + func toDictionary() -> [String: AnyObject]? { return NSKeyedUnarchiver.unarchiveObject(with: self) as? [String: AnyObject] } diff --git a/Examples/OSX/AppDelegate.swift b/Examples/OSX/AppDelegate.swift index 18e315b..6b747e6 100644 --- a/Examples/OSX/AppDelegate.swift +++ b/Examples/OSX/AppDelegate.swift @@ -3,42 +3,36 @@ import Sodium @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { - @IBOutlet weak var window: NSWindow! - - + func applicationDidFinishLaunching(aNotification: NSNotification) { - // Insert code here to initialize your application - let sodium = Sodium() let aliceKeyPair = sodium.box.keyPair()! let bobKeyPair = sodium.box.keyPair()! let message = "My Test Message".toData()! - + print("Original Message:\(String(describing: message.toString()))") - + let encryptedMessageFromAliceToBob: Data = sodium.box.seal( message: message, recipientPublicKey: bobKeyPair.publicKey, senderSecretKey: aliceKeyPair.secretKey)! - + print("Encrypted Message:\(encryptedMessageFromAliceToBob)") - + let messageVerifiedAndDecryptedByBob = sodium.box.open( nonceAndAuthenticatedCipherText: encryptedMessageFromAliceToBob, senderPublicKey: bobKeyPair.publicKey, recipientSecretKey: aliceKeyPair.secretKey) - + print("Decrypted Message:\(String(describing: messageVerifiedAndDecryptedByBob!.toString()))") - + } - + func applicationWillTerminate(aNotification: NSNotification) { - // Insert code here to tear down your application + } - - } diff --git a/Examples/OSX/Info.plist b/Examples/OSX/Info.plist index 100e151..1f7ff29 100644 --- a/Examples/OSX/Info.plist +++ b/Examples/OSX/Info.plist @@ -25,7 +25,7 @@ LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright - Copyright © 2015 Frank Denis. All rights reserved. + Copyright © 2015-2017 Frank Denis. All rights reserved. NSMainNibFile MainMenu NSPrincipalClass diff --git a/Examples/iOS/AppDelegate.swift b/Examples/iOS/AppDelegate.swift index 7224d5a..b81915b 100644 --- a/Examples/iOS/AppDelegate.swift +++ b/Examples/iOS/AppDelegate.swift @@ -1,46 +1,34 @@ -// -// AppDelegate.swift -// Example iOS -// -// Created by RamaKrishna Mallireddy on 19/04/15. -// Copyright (c) 2015 Frank Denis. All rights reserved. -// - import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { - var window: UIWindow? - - + private func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Override point for customization after application launch. return true } - + func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - + func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - + func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - + func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - + func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } - - } diff --git a/Examples/iOS/ViewController.swift b/Examples/iOS/ViewController.swift index 2bba62e..fbedc31 100644 --- a/Examples/iOS/ViewController.swift +++ b/Examples/iOS/ViewController.swift @@ -2,41 +2,36 @@ import UIKit import Sodium class ViewController: UIViewController { - override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. - + let sodium = Sodium() let aliceKeyPair = sodium.box.keyPair()! let bobKeyPair = sodium.box.keyPair()! let message = "My Test Message".toData()! - + print("Original Message:\(String(describing: message.toString()))") - + let encryptedMessageFromAliceToBob: Data = sodium.box.seal( message: message, recipientPublicKey: bobKeyPair.publicKey, senderSecretKey: aliceKeyPair.secretKey)! - + print("Encrypted Message:\(encryptedMessageFromAliceToBob)") - + let messageVerifiedAndDecryptedByBob = sodium.box.open( nonceAndAuthenticatedCipherText: encryptedMessageFromAliceToBob, senderPublicKey: bobKeyPair.publicKey, recipientSecretKey: aliceKeyPair.secretKey) - + print("Decrypted Message:\(String(describing: messageVerifiedAndDecryptedByBob!.toString()))") - + } - + override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. } - - } diff --git a/Sodium.xcodeproj/project.pbxproj b/Sodium.xcodeproj/project.pbxproj index 80b3392..22a43cd 100644 --- a/Sodium.xcodeproj/project.pbxproj +++ b/Sodium.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ 095D805B1A4F35CA000B83F9 /* RandomBytes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 095D805A1A4F35CA000B83F9 /* RandomBytes.swift */; }; 095D805D1A4F4F72000B83F9 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 095D805C1A4F4F72000B83F9 /* Utils.swift */; }; 097F20DA1AF127480088C2FE /* PWHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 097F20D91AF127480088C2FE /* PWHash.swift */; }; + 098DAF041F76E35C00DFB1C3 /* SecretStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09A5AC111F74466700D3200B /* SecretStream.swift */; }; 09A5AC121F74466700D3200B /* SecretStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09A5AC111F74466700D3200B /* SecretStream.swift */; }; 09A943D31A4EB5F500C8A04F /* Sodium.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09A943C71A4EB5F500C8A04F /* Sodium.framework */; }; 09A943DA1A4EB5F500C8A04F /* SodiumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09A943D91A4EB5F500C8A04F /* SodiumTests.swift */; }; @@ -689,6 +690,7 @@ 60C211E71EB73D3900882AD0 /* Auth.swift in Sources */, 094298311EDDAA3B001236B1 /* Stream.swift in Sources */, 6096E7321F194FA800E6599F /* KeyDerivation.swift in Sources */, + 098DAF041F76E35C00DFB1C3 /* SecretStream.swift in Sources */, 90C75EEA1AE3583E00F1E749 /* ShortHash.swift in Sources */, 90C75EEB1AE3583E00F1E749 /* Sign.swift in Sources */, 90C75EEC1AE3583E00F1E749 /* Sodium.swift in Sources */, @@ -994,7 +996,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.vucontacts.swiftodium.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; - SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Debug; @@ -1015,7 +1017,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.vucontacts.swiftodium.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; - SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Release; @@ -1051,7 +1053,7 @@ SDKROOT = macosx; SKIP_INSTALL = YES; SWIFT_INCLUDE_PATHS = "$(PROJECT_DIR)/Sodium $(PROJECT_DIR)/Sodium/libsodium"; - SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Debug; @@ -1084,7 +1086,7 @@ SDKROOT = macosx; SKIP_INSTALL = YES; SWIFT_INCLUDE_PATHS = "$(PROJECT_DIR)/Sodium $(PROJECT_DIR)/Sodium/libsodium"; - SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Release; diff --git a/SodiumTests/ReadmeTests.swift b/SodiumTests/ReadmeTests.swift index f995fed..77bc334 100644 --- a/SodiumTests/ReadmeTests.swift +++ b/SodiumTests/ReadmeTests.swift @@ -7,36 +7,36 @@ class ReadmeTests : XCTestCase { let aliceKeyPair = sodium.box.keyPair()! let bobKeyPair = sodium.box.keyPair()! let message = "My Test Message".data(using:.utf8)! - + let encryptedMessageFromAliceToBob: Data = sodium.box.seal(message: message, recipientPublicKey: bobKeyPair.publicKey, senderSecretKey: aliceKeyPair.secretKey)! - + let messageVerifiedAndDecryptedByBob = sodium.box.open(nonceAndAuthenticatedCipherText: encryptedMessageFromAliceToBob, senderPublicKey: aliceKeyPair.publicKey, recipientSecretKey: bobKeyPair.secretKey) - + XCTAssertNotNil(messageVerifiedAndDecryptedByBob) } - + func testAnonymousEncryptionSealedBoxes() { let sodium = Sodium() let bobKeyPair = sodium.box.keyPair()! let message = "My Test Message".data(using:.utf8)! - + let encryptedMessageToBob = sodium.box.seal(message: message, recipientPublicKey: bobKeyPair.publicKey)! - + let messageDecryptedByBob = sodium.box.open(anonymousCipherText: encryptedMessageToBob, recipientPublicKey: bobKeyPair.publicKey, recipientSecretKey: bobKeyPair.secretKey) - + XCTAssertNotNil(messageDecryptedByBob) } - + func testDetachedSignatures() { let sodium = Sodium() let message = "My Test Message".data(using:.utf8)! @@ -48,7 +48,7 @@ class ReadmeTests : XCTestCase { // signature is valid } } - + func testAttachedSignatures() { let sodium = Sodium() let message = "My Test Message".data(using:.utf8)! @@ -58,7 +58,7 @@ class ReadmeTests : XCTestCase { // signature is valid } } - + func testSecretKeyAuthenticatedEncryption() { let sodium = Sodium() let message = "My Test Message".data(using:.utf8)! @@ -68,24 +68,24 @@ class ReadmeTests : XCTestCase { // authenticator is valid, decrypted contains the original message } } - + func testDeterministicHashing() { let sodium = Sodium() let message = "My Test Message".data(using:.utf8)! let h = sodium.genericHash.hash(message: message) - + XCTAssertNotNil(h) } - + func testKeyedHashing() { let sodium = Sodium() let message = "My Test Message".data(using:.utf8)! let key = "Secret key".data(using:.utf8)! let h = sodium.genericHash.hash(message: message, key: key) - + XCTAssertNotNil(h) } - + func testStreaming() { let sodium = Sodium() let message1 = "My Test ".data(using:.utf8)! @@ -95,33 +95,33 @@ class ReadmeTests : XCTestCase { let _ = stream.update(input: message1) let _ = stream.update(input: message2) let h = stream.final() - + XCTAssertNotNil(h) } - + func testShortOutputHashing() { let sodium = Sodium() let message = "My Test Message".data(using:.utf8)! let key = sodium.randomBytes.buf(length: sodium.shortHash.KeyBytes)! let h = sodium.shortHash.hash(message: message, key: key) - + XCTAssertNotNil(h) } - + func testRandomNumberGeneration() { let sodium = Sodium() let randomData = sodium.randomBytes.buf(length: 1000) - + XCTAssertNotNil(randomData) } - + func testPasswordHashing() { let sodium = Sodium() let password = "Correct Horse Battery Staple".data(using:.utf8)! let hashedStr = sodium.pwHash.str(passwd: password, opsLimit: sodium.pwHash.OpsLimitInteractive, memLimit: sodium.pwHash.MemLimitInteractive)! - + if sodium.pwHash.strVerify(hash: hashedStr, passwd: password) { // Password matches the given hash string } else { @@ -135,63 +135,63 @@ class ReadmeTests : XCTestCase { // hashed doesn't match the current algorithm and the given parameters. } } - + func testZeroingMemory() { let sodium = Sodium() var dataToZero = "Message".data(using:.utf8)! sodium.utils.zero(&dataToZero) } - + func testConstantTimeComparison() { let sodium = Sodium() let secret1 = "Secret key".data(using:.utf8)! let secret2 = "Secret key".data(using:.utf8)! let equality = sodium.utils.equals(secret1, secret2) - + XCTAssertTrue(equality) } - + func testConstantTimeHexdecimalEncoding() { let sodium = Sodium() let data = "Secret key".data(using:.utf8)! let hex = sodium.utils.bin2hex(data) - + XCTAssertNotNil(hex) } - + func testHexDecimalDecoding() { let sodium = Sodium() let data1 = sodium.utils.hex2bin("deadbeef") let data2 = sodium.utils.hex2bin("de:ad be:ef", ignore: " :") - + XCTAssertNotNil(data1) XCTAssertNotNil(data2) } - + func testStream() { let sodium = Sodium() let input = "test".data(using:.utf8)! let key = sodium.stream.key()! let (output, nonce) = sodium.stream.xor(input: input, secretKey: key)! let twice = sodium.stream.xor(input: output, nonce: nonce, secretKey: key)! - + XCTAssertEqual(input, twice) } - + func testAuth() { let sodium = Sodium() let input = "test".data(using:.utf8)! let key = sodium.auth.key()! let tag = sodium.auth.tag(message: input, secretKey: key)! let tagIsValid = sodium.auth.verify(message: input, secretKey: key, tag: tag) - + XCTAssertTrue(tagIsValid) } - + func testKeyDerivation() { let sodium = Sodium() let secretKey = sodium.keyDerivation.key()! - + let subKey1 = sodium.keyDerivation.derive(secretKey: secretKey, index: 0, length: 32, context: "Context!")! @@ -200,30 +200,30 @@ class ReadmeTests : XCTestCase { context: "Context!")! XCTAssertNotEqual(subKey1, subKey2) } - + func testSecretStream() { let sodium = Sodium() let message1 = "Message 1".data(using:.utf8)! let message2 = "Message 2".data(using:.utf8)! let message3 = "Message 3".data(using:.utf8)! - + let secretkey = sodium.secretStream.xchacha20poly1305.key()! - + /* stream encryption */ - + let stream_enc = sodium.secretStream.xchacha20poly1305.initPush(secretKey: secretkey)! let header = stream_enc.header() let encrypted1 = stream_enc.push(message: message1)! let encrypted2 = stream_enc.push(message: message2)! let encrypted3 = stream_enc.push(message: message3, tag: .FINAL)! - + /* stream decryption */ - + let stream_dec = sodium.secretStream.xchacha20poly1305.initPull(secretKey: secretkey, header: header)! let (message1_dec, tag1) = stream_dec.pull(cipherText: encrypted1)! let (message2_dec, tag2) = stream_dec.pull(cipherText: encrypted2)! let (message3_dec, tag3) = stream_dec.pull(cipherText: encrypted3)! - + XCTAssertEqual(message1, message1_dec) XCTAssertEqual(message2, message2_dec) XCTAssertEqual(message3, message3_dec) @@ -231,7 +231,7 @@ class ReadmeTests : XCTestCase { XCTAssertEqual(tag2, .MESSAGE) XCTAssertEqual(tag3, .FINAL) } - + func testBase64() { let sodium = Sodium() let b64 = sodium.utils.bin2base64("data".toData()!)! @@ -240,19 +240,19 @@ class ReadmeTests : XCTestCase { let data1 = sodium.utils.base642bin(b64) let data2 = sodium.utils.base642bin(b64, ignore: " \n") let data3 = sodium.utils.base642bin(b64_2, variant: .URLSAFE_NO_PADDING, ignore: " \n") - + XCTAssertEqual(data1, "data".toData()) XCTAssertEqual(data2, "data".toData()) XCTAssertEqual(data3, "data".toData()) } - + func testPadding() { let sodium = Sodium() var data = "test".toData()! - + // make data.count a multiple of 16 sodium.utils.pad(data: &data, blockSize: 16)! - + // restore original size sodium.utils.unpad(data: &data, blockSize: 16)! } diff --git a/SodiumTests/SodiumTests.swift b/SodiumTests/SodiumTests.swift index c63175e..c74ee1e 100644 --- a/SodiumTests/SodiumTests.swift +++ b/SodiumTests/SodiumTests.swift @@ -15,116 +15,116 @@ extension Data { class SodiumTests: XCTestCase { let sodium = Sodium() - + override func setUp() { super.setUp() } - + override func tearDown() { super.tearDown() } - + func testBox() { let message = "My Test Message".toData()! let aliceKeyPair = sodium.box.keyPair()! let bobKeyPair = sodium.box.keyPair()! - + let encryptedMessageFromAliceToBob: Data = sodium.box.seal(message: message, recipientPublicKey: bobKeyPair.publicKey, senderSecretKey: aliceKeyPair.secretKey)! let decrypted = sodium.box.open(nonceAndAuthenticatedCipherText: encryptedMessageFromAliceToBob, senderPublicKey: bobKeyPair.publicKey, recipientSecretKey: aliceKeyPair.secretKey) XCTAssertEqual(decrypted, message) - + let (encryptedMessageFromAliceToBob2, nonce): (Data, Box.Nonce) = sodium.box.seal(message: message, recipientPublicKey: bobKeyPair.publicKey, senderSecretKey: aliceKeyPair.secretKey)! let decrypted2 = sodium.box.open(authenticatedCipherText: encryptedMessageFromAliceToBob2, senderPublicKey: aliceKeyPair.publicKey, recipientSecretKey: bobKeyPair.secretKey, nonce: nonce) XCTAssertEqual(decrypted2, message) - + let (encryptedMessageFromAliceToBob3, nonce2, mac): (Data, Box.Nonce, Box.MAC) = sodium.box.seal(message: message, recipientPublicKey: bobKeyPair.publicKey, senderSecretKey: aliceKeyPair.secretKey)! let decrypted3 = sodium.box.open(authenticatedCipherText: encryptedMessageFromAliceToBob3, senderPublicKey: aliceKeyPair.publicKey, recipientSecretKey: bobKeyPair.secretKey, nonce: nonce2, mac: mac) XCTAssertEqual(decrypted3, message) - + let userNonce = sodium.randomBytes.buf(length: sodium.box.NonceBytes)! let encryptedMessageFromAliceToBob4: Data = sodium.box.seal(message: message, recipientPublicKey: bobKeyPair.publicKey, senderSecretKey: aliceKeyPair.secretKey, nonce: userNonce)! let decrypted4 = sodium.box.open(authenticatedCipherText: encryptedMessageFromAliceToBob4, senderPublicKey: bobKeyPair.publicKey, recipientSecretKey: aliceKeyPair.secretKey, nonce: userNonce) XCTAssertEqual(message, decrypted4) - + let encryptedMessageToBob: Data = sodium.box.seal(message: message, recipientPublicKey: bobKeyPair.publicKey)! let decrypted5 = sodium.box.open(anonymousCipherText: encryptedMessageToBob, recipientPublicKey: bobKeyPair.publicKey, recipientSecretKey: bobKeyPair.secretKey) XCTAssertEqual(decrypted5, message) - + // beforenm tests // The two beforenm keys calculated by Alice and Bob separately should be identical let aliceBeforenm = sodium.box.beforenm(recipientPublicKey: bobKeyPair.publicKey, senderSecretKey: aliceKeyPair.secretKey)! let bobBeforenm = sodium.box.beforenm(recipientPublicKey: aliceKeyPair.publicKey, senderSecretKey: bobKeyPair.secretKey)! XCTAssertEqual(aliceBeforenm, bobBeforenm) - + // Make sure the encryption using beforenm works let encryptedMessageBeforenm: Data = sodium.box.seal(message: message, beforenm: aliceBeforenm)! let decryptedBeforenm = sodium.box.open(nonceAndAuthenticatedCipherText: encryptedMessageBeforenm, beforenm: aliceBeforenm) XCTAssertEqual(decryptedBeforenm, message) - + let (encryptedMessageBeforenm2, nonceBeforenm): (Data, Box.Nonce) = sodium.box.seal(message: message, beforenm: aliceBeforenm)! let decryptedBeforenm2 = sodium.box.open(authenticatedCipherText: encryptedMessageBeforenm2, beforenm: aliceBeforenm, nonce: nonceBeforenm) XCTAssertEqual(decryptedBeforenm2, message) } - + func testSecretBox() { let message = "My Test Message".toData()! let secretKey = sodium.secretBox.key()! - + // test simple nonce + mac + message box let encrypted: Data = sodium.secretBox.seal(message: message, secretKey: secretKey)! let decrypted = sodium.secretBox.open(nonceAndAuthenticatedCipherText: encrypted, secretKey: secretKey)! XCTAssertEqual(decrypted, message) - + XCTAssertNotEqual(sodium.secretBox.seal(message: message, secretKey: secretKey), encrypted, "Ciphertext of two encryption operations on the same plaintext shouldn't be equal. Make sure the nonce was used only once!") - + XCTAssertNil(sodium.secretBox.open(nonceAndAuthenticatedCipherText: encrypted, secretKey: sodium.secretBox.key()!), "Shouldn't be able to decrypt with a bad key") - + // test (mac + message, nonce) box let (encrypted2, nonce2) = sodium.secretBox.seal(message: message, secretKey: secretKey)! let decrypted2 = sodium.secretBox.open(authenticatedCipherText: encrypted2, secretKey: secretKey, nonce: nonce2) XCTAssertEqual(decrypted2, message) - + XCTAssertNil(sodium.secretBox.open(authenticatedCipherText: encrypted2, secretKey: secretKey, nonce: sodium.secretBox.nonce()), "Shouldn't be able to decrypt with an invalid nonce") - + // test (message, nonce, mac) box let (encrypted3, nonce3, mac3) = sodium.secretBox.seal(message: message, secretKey: secretKey)! let decrypted3 = sodium.secretBox.open(cipherText: encrypted3, secretKey: secretKey, nonce: nonce3, mac: mac3) XCTAssertEqual(decrypted3, message) - + let (encrypted4, nonce4, mac4) = sodium.secretBox.seal(message: message, secretKey: secretKey)! XCTAssertNil(sodium.secretBox.open(cipherText: encrypted4, secretKey: secretKey, nonce: nonce3, mac: mac4), "Shouldn't be able to decrypt with an invalid MAC") XCTAssertNil(sodium.secretBox.open(cipherText: encrypted4, secretKey: secretKey, nonce: nonce4, mac: mac3), "Shouldn't be able to decrypt with an invalid nonce") } - + func testGenericHash() { let message = "My Test Message".toData()! let h1 = sodium.utils.bin2hex(sodium.genericHash.hash(message: message)!)! XCTAssertEqual(h1, "64a9026fca646c31df54426ad15a341e2444d8a1863d57eb27abecf239609f75") - + let key = sodium.utils.hex2bin("64 a9 02 6f ca 64 6c 31 df 54", ignore: " ") let h2 = sodium.utils.bin2hex(sodium.genericHash.hash(message: message, key: key)!)! XCTAssertEqual(h2, "1773f324cba2e7b0017e32d7e44f7afd1036c5d4ef9a80ae0e52e95a629844cd") - + let h3 = sodium.utils.bin2hex(sodium.genericHash.hash(message: message, key: key, outputLength: sodium.genericHash.BytesMax)!)! XCTAssertEqual(h3, "cba85e39f2d03923b2f66aba99b204333edc34a8443ab1700f7920c7abcc6639963a953f35162a520b21072ab906457d21f1645e6e3985858ee95a84d0771f07") - + let s1 = sodium.genericHash.initStream()! XCTAssertTrue(s1.update(input: message)) let h4 = sodium.utils.bin2hex(s1.final()!)! XCTAssertEqual(h4, h1) - + let s2 = sodium.genericHash.initStream(key: key, outputLength: sodium.genericHash.Bytes)! XCTAssertTrue(s2.update(input: message)) let h5 = sodium.utils.bin2hex(s2.final()!)! XCTAssertEqual(h5, h2) - + let s3 = sodium.genericHash.initStream(key: key, outputLength: sodium.genericHash.BytesMax)! XCTAssertTrue(s3.update(input: message)) let h6 = sodium.utils.bin2hex(s3.final()!)! XCTAssertEqual(h6, h3) } - + func testRandomBytes() { let randomLen = 100 + Int(sodium.randomBytes.uniform(upperBound: 100)) let random1 = sodium.randomBytes.buf(length: randomLen)! @@ -132,7 +132,7 @@ class SodiumTests: XCTestCase { XCTAssertEqual(random1.count, randomLen) XCTAssertEqual(random2.count, randomLen) XCTAssertNotEqual(random1, random2) - + var c1 = 0 let ref1 = self.sodium.randomBytes.random() for _ in (0..<100) { @@ -141,7 +141,7 @@ class SodiumTests: XCTestCase { } } XCTAssert(c1 < 10) - + var c2 = 0 let ref2 = self.sodium.randomBytes.uniform(upperBound: 100_000) for _ in (0..<100) { @@ -150,65 +150,65 @@ class SodiumTests: XCTestCase { } } XCTAssert(c2 < 10) - + let seed = sodium.utils.hex2bin("00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff", ignore: " ")! let randomd = sodium.utils.bin2hex(sodium.randomBytes.deterministic(length: 10, seed: seed)!)! XCTAssertEqual(randomd, "444dc0602207c270b93f") } - + func testShortHash() { let message = "My Test Message".toData()! let key = sodium.utils.hex2bin("00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff", ignore: " ")! let h = sodium.utils.bin2hex(sodium.shortHash.hash(message: message, key: key)!)! XCTAssertEqual(h, "bb9be85c918015ea") } - + func testSignature() { let message = "My Test Message".toData()! let keyPair = sodium.sign.keyPair(seed: sodium.utils.hex2bin("00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff", ignore: " ")!)! let signedMessage = sodium.sign.sign(message: message, secretKey: keyPair.secretKey)! XCTAssertEqual(sodium.utils.bin2hex(signedMessage)!, "ce8437d58a27c4d91426d35b24cfaf1e49f95b213c15eddb198f4a8d24c0fdd0df3e7f7a894f60ec15cff25b5f6f27399ce01db0e2649fc54c91cafb8dd48a094d792054657374204d657373616765") - + let signature = sodium.sign.signature(message: message, secretKey: keyPair.secretKey)! XCTAssertEqual(sodium.utils.bin2hex(signature)!, "ce8437d58a27c4d91426d35b24cfaf1e49f95b213c15eddb198f4a8d24c0fdd0df3e7f7a894f60ec15cff25b5f6f27399ce01db0e2649fc54c91cafb8dd48a09") - + XCTAssertTrue(sodium.sign.verify(signedMessage: signedMessage, publicKey: keyPair.publicKey)) XCTAssertTrue(sodium.sign.verify(message: message, publicKey: keyPair.publicKey, signature: signature)) - + let unsignedMessage = sodium.sign.open(signedMessage: signedMessage, publicKey: keyPair.publicKey)! XCTAssertEqual(unsignedMessage, message) } - + func testUtils() { var dataToZero = Data(bytes: [1, 2, 3, 4] as [UInt8]) sodium.utils.zero(&dataToZero) XCTAssert(dataToZero == Data(bytes: [0, 0, 0, 0] as [UInt8])) - + var dataToZero2 = Data(bytes: [1, 2, 3, 4] as [UInt8]) sodium.utils.zero(&dataToZero2) XCTAssert(dataToZero2 == Data(bytes: [0, 0, 0, 0,] as [UInt8])) - + let eq1 = Data(bytes: [1, 2, 3, 4] as [UInt8]) let eq2 = Data(bytes: [1, 2, 3, 4] as [UInt8]) let eq3 = Data(bytes: [1, 2, 3, 5] as [UInt8]) let eq4 = Data(bytes: [1, 2, 3] as [UInt8]) - + XCTAssertTrue(sodium.utils.equals(eq1, eq2)) XCTAssertFalse(sodium.utils.equals(eq1, eq3)) XCTAssertFalse(sodium.utils.equals(eq1, eq4)) - + XCTAssertEqual(sodium.utils.compare(eq1, eq2)!, 0) XCTAssertEqual(sodium.utils.compare(eq1, eq3)!, -1) XCTAssertEqual(sodium.utils.compare(eq3, eq2)!, 1) XCTAssertNil(sodium.utils.compare(eq1, eq4)) - + let bin = sodium.utils.hex2bin("deadbeef")! let hex = sodium.utils.bin2hex(bin) XCTAssertEqual(hex, "deadbeef") let bin2 = sodium.utils.hex2bin("de-ad be:ef", ignore: ":- ")! XCTAssertEqual(bin2, bin) } - + func testPwHash() { let passwordLen = 4 + Int(sodium.randomBytes.uniform(upperBound: 64)) let password = sodium.randomBytes.buf(length: passwordLen)! @@ -219,37 +219,37 @@ class SodiumTests: XCTestCase { let password2 = sodium.randomBytes.buf(length: passwordLen)! let verify2 = sodium.pwHash.strVerify(hash: hash!, passwd: password2) XCTAssertFalse(verify2) - + let password3 = "My Test Message".toData()! let salt = Data(bytes: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] as [UInt8]) let hash2 = sodium.pwHash.hash(outputLength: 64, passwd: password3, salt: salt, opsLimit: sodium.pwHash.OpsLimitInteractive, memLimit: sodium.pwHash.MemLimitInteractive) XCTAssertEqual(sodium.utils.bin2hex(hash2!)!, "51d659ee6f8790042688274c5bc8a6296390cdc786d2341c3553b01a5c3f7ff1190e04b86a878538b17ef10e74baa19295479f3e3ee587ce571f366fc66e2fdc") - + XCTAssertFalse(sodium.pwHash.strNeedsRehash(hash: hash!, opsLimit: sodium.pwHash.OpsLimitInteractive, memLimit: sodium.pwHash.MemLimitInteractive)) XCTAssertTrue(sodium.pwHash.strNeedsRehash(hash: hash!, opsLimit: sodium.pwHash.OpsLimitSensitive, memLimit: sodium.pwHash.MemLimitSensitive)) } - + func testKeyExchange() { let aliceKeyPair = sodium.keyExchange.keyPair()! let bobKeyPair = sodium.keyExchange.keyPair()! - + let sessionKeyPairForAlice = sodium.keyExchange.sessionKeyPair(publicKey: aliceKeyPair.publicKey, secretKey: aliceKeyPair.secretKey, otherPublicKey: bobKeyPair.publicKey, side: .CLIENT)! let sessionKeyPairForBob = sodium.keyExchange.sessionKeyPair(publicKey: bobKeyPair.publicKey, secretKey: bobKeyPair.secretKey, otherPublicKey: aliceKeyPair.publicKey, side: .SERVER)! - + XCTAssertEqual(sessionKeyPairForAlice.rx, sessionKeyPairForBob.tx) XCTAssertEqual(sessionKeyPairForAlice.tx, sessionKeyPairForBob.rx) } - + func testStream() { let key = sodium.stream.key()! let inputLen = Int(sodium.randomBytes.uniform(upperBound: 1024)) let input = sodium.randomBytes.buf(length: inputLen)! let (output, nonce) = sodium.stream.xor(input: input, secretKey: key)! let twice = sodium.stream.xor(input: output, nonce: nonce, secretKey: key)! - + XCTAssertEqual(input, twice) } - + func testAuth() { let key = sodium.utils.hex2bin("eea6a7251c1e72916d11c2cb214d3c252539121d8e234e652d651fa4c8cff880")! let message = sodium.utils.hex2bin("8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186ac0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74e355a5")! @@ -261,33 +261,33 @@ class SodiumTests: XCTestCase { let verify2 = sodium.auth.verify(message: message, secretKey: key2, tag: tag) XCTAssertFalse(verify2) } - + func testKeyDerivationInputKeyTooShort() { let secretKey = sodium.randomBytes.buf(length: sodium.keyDerivation.KeyBytes - 1)! - + XCTAssertNil(sodium.keyDerivation.derive(secretKey: secretKey, index: 0, length: sodium.keyDerivation.BytesMin, context: "TEST")) } - + func testKeyDerivationInputKeyTooLong() { let secretKey = sodium.randomBytes.buf(length: sodium.keyDerivation.BytesMax + 1)! XCTAssertNil(sodium.keyDerivation.derive(secretKey: secretKey, index: 0, length: sodium.keyDerivation.BytesMin, context: "TEST")) } - + func testKeyDerivationSubKeyTooShort() { let secretKey = sodium.keyDerivation.key()! XCTAssertNil(sodium.keyDerivation.derive(secretKey: secretKey, index: 0, length: sodium.keyDerivation.BytesMin - 1, context: "TEST")) } - + func testKeyDerivationSubKeyTooLong() { let secretKey = sodium.keyDerivation.key()! XCTAssertNil(sodium.keyDerivation.derive(secretKey: secretKey, index: 0, length: sodium.keyDerivation.BytesMax + 1, context: "TEST")) } - + func testKeyDerivationContextTooLong() { let secretKey = sodium.keyDerivation.key()! XCTAssertNil(sodium.keyDerivation.derive(secretKey: secretKey, index: 0, length: sodium.keyDerivation.BytesMin, context: "TEST_SODIUM")) } - + func testKeyDerivation() { let secretKey = sodium.keyDerivation.key()! let subKey1 = sodium.keyDerivation.derive(secretKey: secretKey, index: 0, length: sodium.keyDerivation.BytesMin, context: "TEST")! @@ -295,33 +295,33 @@ class SodiumTests: XCTestCase { let subKey3 = sodium.keyDerivation.derive(secretKey: secretKey, index: 0, length: sodium.keyDerivation.BytesMin, context: "TEST\0")! let subKey4 = sodium.keyDerivation.derive(secretKey: secretKey, index: 1, length: sodium.keyDerivation.BytesMin, context: "TEST")! let subKey5 = sodium.keyDerivation.derive(secretKey: secretKey, index: 0, length: sodium.keyDerivation.BytesMin, context: "test")! - + XCTAssertEqual(subKey1, subKey2, "Equally derived keys must be equal!") XCTAssertEqual(subKey1, subKey3, "Manual padding should result in same key.") - + XCTAssertNotEqual(subKey1, subKey4, "Subkeys with different indices must be different!") XCTAssertNotEqual(subKey1, subKey5, "Subkeys with different contexts must be different!") } - + func testKeyDerivationRegression() { let secretKey = sodium.utils.hex2bin("a9029ec4ec56dd6f3ce5a5fa27a17a005ce73a5b8e77529887f24f73ffa10d67")! let subKey1 = sodium.keyDerivation.derive(secretKey: secretKey, index: 0, length: sodium.keyDerivation.BytesMin, context: "TEST")! let subKey2 = sodium.keyDerivation.derive(secretKey: secretKey, index: 1, length: sodium.keyDerivation.BytesMin, context: "TEST")! - + XCTAssertEqual(sodium.utils.bin2hex(subKey1)!, "40d69c5e6e8b46e399433c9b5c3a7713") XCTAssertEqual(sodium.utils.bin2hex(subKey2)!, "8ba83c1cd5a3be912a80ef2abe1457c5") } - + func testSecretStream() { let secretKey = sodium.secretStream.xchacha20poly1305.key()! XCTAssertEqual(secretKey.count, 32) - + let stream = sodium.secretStream.xchacha20poly1305.initPush(secretKey: secretKey)! let header = stream.header() let encrypted1 = stream.push(message: "message 1".toData()!)! let encrypted2 = stream.push(message: "message 2".toData()!)! let encrypted3 = stream.push(message: "message 3".toData()!, tag: .FINAL)! - + let stream2 = sodium.secretStream.xchacha20poly1305.initPull(secretKey: secretKey, header: header)! let (message1, tag1) = stream2.pull(cipherText: encrypted1)! let (message2, tag2) = stream2.pull(cipherText: encrypted2)! @@ -334,20 +334,20 @@ class SodiumTests: XCTestCase { XCTAssertEqual(message3, "message 3".toData()!) XCTAssertNil(stream2.pull(cipherText: encrypted3)) } - + func testBase64() { let bin = "test".toData()! let b64 = sodium.utils.bin2base64(bin)! let bin2 = sodium.utils.base642bin(b64)! XCTAssertEqual(b64, "dGVzdA==") XCTAssertEqual(bin2, bin) - + let b64_nopad = sodium.utils.bin2base64(bin, variant: .URLSAFE_NO_PADDING)! let bin2_nopad = sodium.utils.base642bin(b64_nopad, variant: .URLSAFE_NO_PADDING)! XCTAssertEqual(b64_nopad, "dGVzdA") XCTAssertEqual(bin2_nopad, bin) } - + func testPad() { var data = "test".toData()! sodium.utils.pad(data: &data, blockSize: 16)!