Browse Source

Improve docs

Rob Napier 12 years ago
parent
commit
1efa82813e

+ 23 - 0
AppledocSettings.plist

@@ -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 - 0
README.md

@@ -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.

BIN
RNCryptor.xcodeproj/project.xcworkspace/xcuserdata/rnapier.xcuserdatad/UserInterfaceState.xcuserstate


+ 102 - 34
RNCryptor/RNCryptor.h

@@ -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
@@ -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
@@ -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
@@ -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
 

+ 24 - 21
RNCryptor/RNCryptor.m

@@ -40,9 +40,7 @@ static NSUInteger NextMultipleOfUnit(NSUInteger size, NSUInteger unit)
 @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)
@@ -98,18 +96,6 @@ static NSUInteger NextMultipleOfUnit(NSUInteger size, NSUInteger unit)
   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;
@@ -119,6 +105,16 @@ static NSUInteger NextMultipleOfUnit(NSUInteger size, NSUInteger unit)
   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];
@@ -152,7 +148,6 @@ static NSUInteger NextMultipleOfUnit(NSUInteger size, NSUInteger unit)
     {
       *error = [NSError errorWithDomain:kRNCryptorErrorDomain code:cryptorStatus userInfo:nil];
     }
-    NSLog(@"%s Could not process data: %d", __PRETTY_FUNCTION__, cryptorStatus);
     return NO;
   }
 
@@ -161,8 +156,7 @@ static NSUInteger NextMultipleOfUnit(NSUInteger size, NSUInteger unit)
     [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)
@@ -303,7 +297,12 @@ static NSUInteger NextMultipleOfUnit(NSUInteger size, NSUInteger unit)
    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;
@@ -344,7 +343,6 @@ static NSUInteger NextMultipleOfUnit(NSUInteger size, NSUInteger unit)
   return result;
 }
 
-
 - (BOOL)decryptFromStream:(NSInputStream *)input toStream:(NSOutputStream *)output password:(NSString *)password error:(NSError **)error
 {
   NSData *encryptionKeySalt;
@@ -408,7 +406,12 @@ static NSUInteger NextMultipleOfUnit(NSUInteger size, NSUInteger unit)
   }
 }
 
-- (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;

+ 4 - 0
RNCryptorTests/RNCryptorTests.m

@@ -27,6 +27,10 @@
 #import "RNCryptorTests.h"
 #import "RNCryptor.h"
 
+@interface RNCryptor (Private)
+- (NSData *)randomDataOfLength:(size_t)length;
+@end
+
 @implementation RNCryptorTests
 
 - (void)setUp

+ 0 - 1
builddoc

@@ -1 +0,0 @@
-appledoc --project-name RNCryptor --project-company "Rob Napier" --company-id net.robnapier --output doc RNCryptor