Skip to content

Commit

Permalink
Improve docs
Browse files Browse the repository at this point in the history
  • Loading branch information
rnapier committed Mar 20, 2012
1 parent 872f67b commit 1efa828
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 56 deletions.
23 changes: 23 additions & 0 deletions AppledocSettings.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>--ignore</key>
<array>
<string>RNCryptorTests</string>
</array>
<key>--project-name</key>
<string>RNCryptor</string>
<key>--project-company</key>
<string>Rob Napier</string>
<key>--company-id</key>
<string>net.robnapier</string>
<key>--create-docset</key>
<false/>
<key>--install-docset</key>
<false/>
<key>--output</key>
<string>doc</string>
</dict>
</plist>
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ The same encryption and decryption can be processed from one `NSURL` or `NSStrea
password:password
error:&error];

# API Documentation

Full API information is available at http://rnapier.github.com/RNCryptor/doc/html/Classes/RNCryptor.html.

# Building

Comes packaged as a static library, but the `RNCryptor.h` and `RNCryptor.m` files can be dropped into any project.
Expand Down
Binary file not shown.
136 changes: 102 additions & 34 deletions RNCryptor/RNCryptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,14 @@ extern NSString *const kRNCryptorErrorDomain;
typedef void (^RNCryptorReadCallback)(NSData *readData);
typedef void (^RNCryptorWriteCallback)(NSData *writeData);

/** Encryptor/Decryptor for iOS.
Provides an easy-to-use, Objective-C interface to the AES functionality of CommonCrypto. Simplifies correct handling of
password stretching (PBKDF2), salting, and IV. For more information on these terms, see "Properly encrypting with AES
with CommonCrypto" http://robnapier.net/blog/aes-commoncrypto-564
RNCryptor is immutable, stateless and thread-safe. A given cryptor object may be used simultaneously on multiple
threads, and can be reused to encrypt or decrypt an arbitrary number of independent messages.
Links for discussion of several algorithm choices:
http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
http://www.daemonology.net/blog/2009-06-24-encrypt-then-mac.html
http://www.daemonology.net/blog/2009-07-31-thoughts-on-AES.html
-- Note that the output of PBKDF2 should be considered "random" in this context. I do not believe that the AES-256
related-key attacks are generally applicable to the likely uses of this framework (encrypting data against
human-generated password, or against true random keys).
Requires Security.framework.
NOTE: Mac support should be possible, but requires replacing SecCopyRandomBytes() and switching from AES-CTR to AES-CBC.
This may be resolved in 10.8.
/** Encryptor/Decryptor for iOS
Provides an easy-to-use, Objective-C interface to the AES functionality of CommonCrypto. Simplifies correct handling of
password stretching (PBKDF2), salting, and IV. For more information on these terms, see "Properly encrypting with AES
with CommonCrypto," and iOS 5 Programming Pushing the Limits, Chapter 11. Also includes automatic HMAC handling to integrity-check messages.
RNCryptor is immutable, stateless and thread-safe. A given cryptor object may be used simultaneously on multiple threads,
and can be reused to encrypt or decrypt an arbitrary number of independent messages.
*/

@interface RNCryptor : NSObject
Expand Down Expand Up @@ -128,8 +115,10 @@ typedef void (^RNCryptorWriteCallback)(NSData *writeData);
* @param toStream Stream to write. May be opened or unopened.
* @param encryptionKey Encryption key of correct length for algorithm. This is not a password. No hashing or PBKDF will be applied.
* @param IV Initialization vector of correct length for algorithm. For "no IV," you must pass a zero-filled block of the correct length. This is strongly discouraged.
* @param HMACKey HMAC key. This can be of any length. It is discouraged to make this the same as `encryptionKey`.
* @param HMACKey HMAC key. This can be of any length. It is discouraged to make this the same as `encryptionKey`. If HMACKey is `nil`, no HMAC will be written.
* @param error If there is an error, this will contain the `NSError` by reference
* @returns `YES` on success. `NO` on failure, and `error` will contain the error object.
* @returns `
*/
- (BOOL)encryptFromStream:(NSInputStream *)fromStream
toStream:(NSOutputStream *)toStream
Expand All @@ -138,6 +127,18 @@ typedef void (^RNCryptorWriteCallback)(NSData *writeData);
HMACKey:(NSData *)HMACKey
error:(NSError **)error;

/** Decrypt from a stream, to a stream, provided a key (not password), IV, and optional HMAC key.
* The HMAC of the ciphertext will be read from the end of the stream if an HMAC key is provided. If there is an HMAC,
* then it must match, or this method will return `NO`.
*
* @param fromStream Stream to read. May be opened or unopened.
* @param toStream Stream to write. May be opened or unopened.
* @param encryptionKey Encryption key of correct length for algorithm. This is not a password. No hashing or PBKDF will be applied.
* @param IV Initialization vector of correct length for algorithm. For "no IV," you must pass a zero-filled block of the correct length. This is strongly discouraged.
* @param HMACKey HMAC key, matching the encryption key.
* @param error If there is an error, this will contain the `NSError` by reference
* @returns `YES` on success. `NO` on failure (including HMAC mismatch), and `error` will contain the error object.
*/
- (BOOL)decryptFromStream:(NSInputStream *)input
toStream:(NSOutputStream *)output
encryptionKey:(NSData *)encryptionKey
Expand All @@ -146,36 +147,103 @@ typedef void (^RNCryptorWriteCallback)(NSData *writeData);
error:(NSError **)error;


///---------------------------------------------------------------------------------------
/// @name Password-based operations
///---------------------------------------------------------------------------------------

- (BOOL)decryptFromStream:(NSInputStream *)input
toStream:(NSOutputStream *)output
/** Encrypt from a stream, to a stream, provided a password.
* Automatically generates required salts and IV. Prepends header and appends HMAC.
* Full format is described at https://github.com/rnapier/RNCryptor/wiki/Data-Format
*
* @param fromStream Stream to read. May be opened or unopened.
* @param toStream Stream to write. May be opened or unopened.
* @param password Password to use for encryption
* @param error If there is an error, this will contain the `NSError` by reference
* @returns `YES` on success. `NO` on failure, and `error` will contain the error object.
*/
- (BOOL)encryptFromStream:(NSInputStream *)fromStream
toStream:(NSOutputStream *)toStream
password:(NSString *)password
error:(NSError **)error;

- (BOOL)decryptFromURL:(NSURL *)inURL
toURL:(NSURL *)outURL
/** Encrypt from a URL, to a URL, provided a password.
* Automatically generates required salts and IV. Prepends header and appends HMAC.
* Full format is described at https://github.com/rnapier/RNCryptor/wiki/Data-Format
*
* @param fromURL URL to read.
* @param toURL URL to write.
* @param append Should output be appended rather than overwritng?
* @param password Password to use for encryption
* @param error If there is an error, this will contain the `NSError` by reference
* @returns `YES` on success. `NO` on failure, and `error` will contain the error object.
*/
- (BOOL)encryptFromURL:(NSURL *)fromURL
toURL:(NSURL *)toURL
append:(BOOL)append
password:(NSString *)password
error:(NSError **)error;

- (NSData *)decryptData:(NSData *)ciphertext password:(NSString *)password error:(NSError **)error;

/** Encrypt data, provided a password.
* Automatically generates required salts and IV. Prepends header and appends HMAC.
* Full format is described at https://github.com/rnapier/RNCryptor/wiki/Data-Format
*
* @param plaintext Data to encrypt
* @param password Password to use for encryption
* @param error If there is an error, this will contain the `NSError` by reference
* @returns Encrypted data, or `nil` if there was an error.
*/
- (NSData *)encryptData:(NSData *)plaintext password:(NSString *)password error:(NSError **)error;

- (BOOL)encryptFromStream:(NSInputStream *)input
toStream:(NSOutputStream *)output
/** Decrypt from a stream, to a stream, provided a password.
* Stream must be in format described at https://github.com/rnapier/RNCryptor/wiki/Data-Format, with header,
* required salts and IV prepended, and HMAC appended.
*
* @param fromStream Stream to read. May be opened or unopened.
* @param toStream Stream to write. May be opened or unopened.
* @param password Password to use for decryption
* @returns `YES` on success. `NO` on failure, and `error` will contain the error object.
* @param error If there is an error, this will contain the `NSError` by reference
*/
- (BOOL)decryptFromStream:(NSInputStream *)fromStream
toStream:(NSOutputStream *)toStream
password:(NSString *)password
error:(NSError **)error;

- (BOOL)encryptFromURL:(NSURL *)inURL
toURL:(NSURL *)outURL
/** Decrypt from a URL, to a URL, provided a password.
* URL contents must be in format described at https://github.com/rnapier/RNCryptor/wiki/Data-Format, with header,
* required salts and IV prepended, and HMAC appended.
*
* @param fromURL URL to read.
* @param toURL URL to write.
* @param append Should output be appended rather than overwritng?
* @param password Password to use for decryption
* @param error If there is an error, this will contain the `NSError` by reference
* @returns `YES` on success. `NO` on failure, and `error` will contain the error object.
*/
- (BOOL)decryptFromURL:(NSURL *)fromURL
toURL:(NSURL *)toURL
append:(BOOL)append
password:(NSString *)password
error:(NSError **)error;

- (NSData *)encryptData:(NSData *)plaintext password:(NSString *)password error:(NSError **)error;
/** Decrypt data, provided a password.
* Data must be in format described at https://github.com/rnapier/RNCryptor/wiki/Data-Format, with header,
* required salts and IV prepended, and HMAC appended.
*
* @param ciphertext Data to decrypt
* @param password Password to use for decryption
* @param error If there is an error, this will contain the `NSError` by reference
* @returns Decrypted data, or `nil` if there was an error.
*/
- (NSData *)decryptData:(NSData *)ciphertext password:(NSString *)password error:(NSError **)error;

/** Generate key given a password and salt using a PBKDF
*
* @param password Password to use for PBKDF
* @param salt Salt for password
* @returns Key
*/
- (NSData *)keyForPassword:(NSString *)password salt:(NSData *)salt;
- (NSData *)randomDataOfLength:(size_t)length;

@end

Expand Down
45 changes: 24 additions & 21 deletions RNCryptor/RNCryptor.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ - (BOOL)_RNGetData:(NSData **)data maxLength:(NSUInteger)maxLength error:(NSErro
@end

@implementation NSInputStream (RNCryptor)
- (BOOL)_RNGetData:(NSData **)data
maxLength:(NSUInteger)maxLength
error:(NSError **)error
- (BOOL)_RNGetData:(NSData **)data maxLength:(NSUInteger)maxLength error:(NSError **)error
{
NSMutableData *buffer = [NSMutableData dataWithLength:maxLength];
if ([self read:buffer.mutableBytes maxLength:maxLength] < 0)
Expand Down Expand Up @@ -98,18 +96,6 @@ - (RNCryptor *)initWithSettings:(RNCryptorSettings *)settings
return self;
}

- (NSData *)randomDataOfLength:(size_t)length
{
NSMutableData *data = [NSMutableData dataWithLength:length];

int result = SecRandomCopyBytes(kSecRandomDefault,
length,
data.mutableBytes);
NSAssert(result == 0, @"Unable to generate random bytes: %d", errno);

return data;
}

+ (RNCryptor *)AES256Cryptor
{
static dispatch_once_t once;
Expand All @@ -119,6 +105,16 @@ + (RNCryptor *)AES256Cryptor
return AES256Cryptor;
}

- (NSData *)randomDataOfLength:(size_t)length
{
NSMutableData *data = [NSMutableData dataWithLength:length];

int result = SecRandomCopyBytes(kSecRandomDefault, length, data.mutableBytes);
NSAssert(result == 0, @"Unable to generate random bytes: %d", errno);

return data;
}

- (NSData *)keyForPassword:(NSString *)password salt:(NSData *)salt
{
NSMutableData *derivedKey = [NSMutableData dataWithLength:self.settings.keySize];
Expand Down Expand Up @@ -152,7 +148,6 @@ - (BOOL)processResult:(CCCryptorStatus)cryptorStatus
{
*error = [NSError errorWithDomain:kRNCryptorErrorDomain code:cryptorStatus userInfo:nil];
}
NSLog(@"%s Could not process data: %d", __PRETTY_FUNCTION__, cryptorStatus);
return NO;
}

Expand All @@ -161,8 +156,7 @@ - (BOOL)processResult:(CCCryptorStatus)cryptorStatus
[outData setLength:length];

[output open];
NSInteger bytesWritten = [output write:outData.bytes
maxLength:outData.length];
NSInteger bytesWritten = [output write:outData.bytes maxLength:outData.length];
if (bytesWritten != outData.length)
{
if (error)
Expand Down Expand Up @@ -303,7 +297,12 @@ - (BOOL)performOperation:(CCOperation)anOperation
return YES;
}

- (BOOL)decryptFromStream:(NSInputStream *)input toStream:(NSOutputStream *)output encryptionKey:(NSData *)encryptionKey IV:(NSData *)IV HMACKey:(NSData *)HMACKey error:(NSError **)error
- (BOOL)decryptFromStream:(NSInputStream *)input
toStream:(NSOutputStream *)output
encryptionKey:(NSData *)encryptionKey
IV:(NSData *)IV
HMACKey:(NSData *)HMACKey
error:(NSError **)error
{
RNCryptorWriteCallback readCallback = nil;
__block CCHmacContext HMACContext;
Expand Down Expand Up @@ -344,7 +343,6 @@ - (BOOL)decryptFromStream:(NSInputStream *)input toStream:(NSOutputStream *)outp
return result;
}


- (BOOL)decryptFromStream:(NSInputStream *)input toStream:(NSOutputStream *)output password:(NSString *)password error:(NSError **)error
{
NSData *encryptionKeySalt;
Expand Down Expand Up @@ -408,7 +406,12 @@ - (NSData *)decryptData:(NSData *)ciphertext password:(NSString *)password error
}
}

- (BOOL)encryptFromStream:(NSInputStream *)input toStream:(NSOutputStream *)output encryptionKey:(NSData *)encryptionKey IV:(NSData *)IV HMACKey:(NSData *)HMACKey error:(NSError **)error
- (BOOL)encryptFromStream:(NSInputStream *)input
toStream:(NSOutputStream *)output
encryptionKey:(NSData *)encryptionKey
IV:(NSData *)IV
HMACKey:(NSData *)HMACKey
error:(NSError **)error
{
RNCryptorWriteCallback writeCallback = nil;
__block CCHmacContext HMACContext;
Expand Down
4 changes: 4 additions & 0 deletions RNCryptorTests/RNCryptorTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
#import "RNCryptorTests.h"
#import "RNCryptor.h"

@interface RNCryptor (Private)
- (NSData *)randomDataOfLength:(size_t)length;
@end

@implementation RNCryptorTests

- (void)setUp
Expand Down
1 change: 0 additions & 1 deletion builddoc

This file was deleted.

0 comments on commit 1efa828

Please sign in to comment.