snej@0
|
1 |
//
|
snej@0
|
2 |
// Cryptor.h
|
snej@0
|
3 |
// MYCrypto
|
snej@0
|
4 |
//
|
snej@0
|
5 |
// Created by Jens Alfke on 3/21/09.
|
snej@0
|
6 |
// Copyright 2009 Jens Alfke. All rights reserved.
|
snej@0
|
7 |
//
|
snej@0
|
8 |
|
snej@0
|
9 |
#import <Foundation/Foundation.h>
|
snej@0
|
10 |
#import <CommonCrypto/CommonCryptor.h>
|
snej@0
|
11 |
|
snej@0
|
12 |
|
snej@2
|
13 |
/** Symmetric encryption: a streaming interface for encrypting/decrypting data.
|
snej@2
|
14 |
This is a simple Cocoa wrapper for CommonCrypto/commonCryptor.h. It will probably be
|
snej@2
|
15 |
merged into, or integrated with, MYSymmetricKey. */
|
snej@0
|
16 |
@interface MYCryptor : NSObject
|
snej@0
|
17 |
{
|
snej@1
|
18 |
@private
|
snej@0
|
19 |
NSData *_key;
|
snej@0
|
20 |
CCOperation _operation;
|
snej@0
|
21 |
CCAlgorithm _algorithm;
|
snej@0
|
22 |
CCOptions _options;
|
snej@0
|
23 |
CCCryptorRef _cryptor;
|
snej@0
|
24 |
NSError *_error;
|
snej@0
|
25 |
NSOutputStream *_outputStream;
|
snej@0
|
26 |
NSMutableData *_output;
|
snej@0
|
27 |
size_t _outputExtraBytes;
|
snej@0
|
28 |
}
|
snej@0
|
29 |
|
snej@2
|
30 |
/** Returns a randomly-generated symmetric key of the desired length (in bits).
|
snej@2
|
31 |
* @param lengthInBits The length of the desired key, in bits (not bytes).
|
snej@2
|
32 |
*/
|
snej@2
|
33 |
+ (NSData*) randomKeyOfLength: (size_t)lengthInBits;
|
snej@0
|
34 |
|
snej@2
|
35 |
/** Converts a passphrase into a symmetric key of the desired length (in bits).
|
snej@2
|
36 |
* The same passphrase (and salt) will always return the same key, so you can use this method
|
snej@2
|
37 |
* to encrypt and decrypt data using a user-entered passphrase, without having to store the key
|
snej@2
|
38 |
* itself in the keychain.
|
snej@2
|
39 |
* @param lengthInBits The length of the desired key, in bits (not bytes).
|
snej@2
|
40 |
* @param passphrase The user-entered passphrase.
|
snej@2
|
41 |
* @param salt An arbitrary value whose description will be appended to the passphrase before
|
snej@2
|
42 |
* hashing, to perturb the resulting bits. The purpose of this is to make it harder for
|
snej@2
|
43 |
* an attacker to brute-force the key using a precompiled list of digests of common
|
snej@2
|
44 |
* passwords. Changing the salt changes the key, so you need to pass the same value when
|
snej@2
|
45 |
* re-deriving the key as you did when first generating it.
|
snej@2
|
46 |
*/
|
snej@2
|
47 |
+ (NSData*) keyOfLength: (size_t)lengthInBits
|
snej@2
|
48 |
fromPassphrase: (NSString*)passphrase
|
snej@2
|
49 |
salt: (id)salt;
|
snej@0
|
50 |
|
snej@0
|
51 |
/** Creates a MYCryptor configured to encrypt data. */
|
snej@0
|
52 |
- (id) initEncryptorWithKey: (NSData*)key
|
snej@0
|
53 |
algorithm: (CCAlgorithm)algorithm;
|
snej@0
|
54 |
|
snej@0
|
55 |
/** Creates a MYCryptor configured to decrypt data. */
|
snej@0
|
56 |
- (id) initDecryptorWithKey: (NSData*)key
|
snej@0
|
57 |
algorithm: (CCAlgorithm)algorithm;
|
snej@0
|
58 |
|
snej@0
|
59 |
/** The encryption/decryption key; same as the 'key' parameter to the initializer. */
|
snej@0
|
60 |
@property (readonly) NSData *key;
|
snej@0
|
61 |
|
snej@0
|
62 |
/** The cipher to use; initial value is the 'algorithm' parameter to the initializer.
|
snej@1
|
63 |
You can change this <i>before</i> the first call to -addData:, but not after. */
|
snej@0
|
64 |
@property CCAlgorithm algorithm;
|
snej@0
|
65 |
|
snej@0
|
66 |
/** Block-mode cipher options; you can set flags to enable PKCS7 padding or ECB mode
|
snej@0
|
67 |
(default is CBC.)
|
snej@1
|
68 |
You can change this <i>before</i> the first call to -addData:, but not after. */
|
snej@0
|
69 |
@property CCOptions options;
|
snej@0
|
70 |
|
snej@1
|
71 |
/** Setting this property tells the cryptor to send its output to the stream,
|
snej@1
|
72 |
instead of accumulating it in the outputData property.
|
snej@1
|
73 |
You can change this <i>before</i> the first call to -addData:, but not after. */
|
snej@1
|
74 |
@property (retain) NSOutputStream *outputStream;
|
snej@1
|
75 |
|
snej@0
|
76 |
/** The error state, if any, of this cryptor.
|
snej@0
|
77 |
After -addData: or -finish: returns NO, check this property. */
|
snej@0
|
78 |
@property (readonly, retain) NSError *error;
|
snej@0
|
79 |
|
snej@0
|
80 |
/** Adds input data.
|
snej@0
|
81 |
@return YES if the operation succeeded, NO if it failed. */
|
snej@0
|
82 |
- (BOOL) addData: (NSData*)data;
|
snej@0
|
83 |
|
snej@0
|
84 |
/** Finishes up the encryption/decryption and flushes the remaining bytes of output.
|
snej@0
|
85 |
After this is called, you cannot add any more bytes of data.
|
snej@0
|
86 |
@return YES if the operation succeeded, NO if it failed. */
|
snej@0
|
87 |
- (BOOL) finish;
|
snej@0
|
88 |
|
snej@0
|
89 |
/** The output of the cryptor. Accessing this property implicitly calls -finish, so don't
|
snej@0
|
90 |
do it until you've added all of the input. (And don't add any more input afterwards.)
|
snej@0
|
91 |
This property will be nil if the outputStream property has been set. */
|
snej@0
|
92 |
@property (readonly) NSData *outputData;
|
snej@0
|
93 |
|
snej@0
|
94 |
@end
|
snej@0
|
95 |
|
snej@0
|
96 |
|
snej@0
|
97 |
|
snej@0
|
98 |
/** NSError domain for MYCryptor operations. Error code is interpreted as a CCCryptorStatus,
|
snej@0
|
99 |
with additional error code(s) defined below. */
|
snej@0
|
100 |
extern NSString* const CryptorErrorDomain;
|
snej@0
|
101 |
|
snej@0
|
102 |
enum {
|
snej@0
|
103 |
/** Indicates that the outputStream couldn't write all the bytes given to it (this is legal
|
snej@0
|
104 |
behavior for an NSOutputStream, but MYCryptor can't handle this yet.) */
|
snej@0
|
105 |
kMYCryptorErrorOutputStreamChoked = -777000
|
snej@0
|
106 |
};
|