-1

I am currently trying to make my own password manager application similar to master password, which uses an algorithm to generate passwords so they do not have to be stored on the clients computer or online.

To achieve this I have decided to use the ChaCha20 cipher algorithm using the CryptoSwift library. Here is the code I have at the moment (OS X Application):

import Cocoa
import CryptoSwift

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!


    func applicationDidFinishLaunching(aNotification: NSNotification) {

        do
        {
            let UInt8String = "Test".utf8
            print("UTF8 string: \(UInt8String)")
            let UInt8Array = Array(UInt8String)
            print("UTF8 array: \(UInt8Array)")

            let encrypted = try ChaCha20(key: "Key", iv: "Iv")!.encrypt(UInt8Array)

            print("Encrypted data: \(encrypted)")
        } catch _ {

        }
    }

    func applicationWillTerminate(aNotification: NSNotification) {
        // Insert code here to tear down your application
    }
}

The line where I am getting the error on is let encrypted = try ChaCha20(key: "Key", iv: "Iv")!.encrypt(UInt8Array). The error that I am getting is "Fatal error: unexpectedly found nil while unwrapping an Optional value". This is probably due to the the '!' before the encrypt method since everything else works before that. I have tried replacing the '!' with a '?', however the variable encrypted is then equal to nil, if I remove the '!' or '?' altogether I get a syntax error.

How would I fix the issue on the let encrypted = try ChaCha20(key: "Key", iv: "Iv")!.encrypt(UInt8Array) line?

jww
  • 97,681
  • 90
  • 411
  • 885
iProgram
  • 6,057
  • 9
  • 39
  • 80

2 Answers2

5

The keysize of ChaCha20 is either 128 or 256 bits (16 or 32 bytes). You're passing 3 bytes. The "IV" (really nonce here) is 8 bytes. You're passing 2. You should not expect this to construct a cipher object. Since it doesn't, you get nil, and then when you apply ! it crashes as you've requested (that's what ! means).

You need to create a random key and nonce of the correct sizes. If you have a password, you need to convert it to a key using a proper KDF such as PBKDF2.

If any of this is unclear to you, then you do not yet have the skill set required to build a secure password manager and you really should stop and study how to securely implement cryptography first. I don't mean you're a bad developer or unfamiliar with Cocoa development. It is very easy to create completely insecure encryption systems that look secure and are made out of "secure" components. If this is an area that interests you, I strongly recommend the Cryptography I course from Coursera. Cryptography isn't some deep mystery that can't be leaned with a little effort, but it is certainly not intuitive and the vast majority of crypto tools out there (including CryptoSwift) assume you already know what you're doing.

If you want something off-the-shelf that handles many of the hard parts for you, then you may want to look at RNCryptor. That may be sufficient for your own personal password manager, but I would never suggests building a password manager for others without a strong foundation in building crypto systems (even if you chose RNCryptor to implement it). Password managers are just too security-critical to be built without a strong foundation in the subject.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
1

You wrote:

This is probably due to the the '!' before the encrypt method since everything else works before that. I have tried replacing the '!' with a '?', however the variable encrypted is then equal to nil

That is the right answer as well. The question is why function / or constructor ChaCha20(key: "Key", iv: "Iv") returns nil and didn't throw the error. There are two possibilities, (a) ChaCha20 don't throws an error by definition or (b) the parameters are OK and the result is still nil. You have to check CryptoSwift framework documentation, because your trouble is that ChaCha20 failed for some reason, not your own code.

UPDATE! I checked CryptoSwift and found

public init?(key:[UInt8], iv:[UInt8]) {
        if let c = contextSetup(iv: iv, key: key) {
            context = c
        } else {
            return nil
        }
    }

The parameters in your code are wrong (you use String and not [UInt8]). Are you sure, that you are using valid version of the library? You didn't receive any errors from compiler, because your code can be executed ... Check it, please.

user3441734
  • 16,722
  • 2
  • 40
  • 59
  • Look in https://github.com/krzyzanowskim/CryptoSwift/blob/master/Sources/CryptoSwift/Foundation/ChaCha20%2BFoundation.swift. There's an extension that accepts UTF8 strings. – Rob Napier Jan 01 '16 at 19:32
  • @RobNapier I can see your answer now, so no other action is required. – user3441734 Jan 01 '16 at 19:35