aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/SPDataAdditions.h2
-rw-r--r--Source/SPDataAdditions.m52
2 files changed, 47 insertions, 7 deletions
diff --git a/Source/SPDataAdditions.h b/Source/SPDataAdditions.h
index 0ceca0d3..118f47e2 100644
--- a/Source/SPDataAdditions.h
+++ b/Source/SPDataAdditions.h
@@ -30,6 +30,8 @@
@interface NSData (SPDataAdditions)
+- (NSData *)sha1Hash;
+
- (NSData *)dataEncryptedWithPassword:(NSString *)password;
- (NSData *)dataDecryptedWithPassword:(NSString *)password;
- (NSData *)compress;
diff --git a/Source/SPDataAdditions.m b/Source/SPDataAdditions.m
index e9eaa927..23280c8b 100644
--- a/Source/SPDataAdditions.m
+++ b/Source/SPDataAdditions.m
@@ -36,11 +36,41 @@
#include <zlib.h>
#include <openssl/aes.h>
-#include <openssl/sha.h>
+#include <CommonCrypto/CommonCrypto.h>
#include <stdlib.h>
+uint32_t LimitUInt32(NSUInteger i);
+
+#pragma mark -
+
@implementation NSData (SPDataAdditions)
+- (NSData *)sha1Hash
+{
+ unsigned char digest[CC_SHA1_DIGEST_LENGTH];
+
+ //let's do it as a one step operation, if it fits
+ if([self length] <= UINT32_MAX) {
+ CC_SHA1([self bytes], (uint32_t)[self length], digest);
+ }
+ // or multi-step if length > 32 bit
+ else {
+ CC_SHA1_CTX ctx;
+ CC_SHA1_Init(&ctx);
+
+ NSUInteger offset = 0;
+ uint32_t len;
+ while((len = LimitUInt32([self length]-offset)) > 0) {
+ CC_SHA1_Update(&ctx, ([self bytes]+offset), len);
+ offset += len;
+ }
+
+ CC_SHA1_Final(digest, &ctx);
+ }
+
+ return [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
+}
+
- (NSData *)dataEncryptedWithPassword:(NSString *)password
{
// Create a random 128-bit initialization vector
@@ -68,10 +98,9 @@
memcpy(paddedBytes + (paddedLength - 4), &bigIntDataLength, 4);
// Create the key from first 128-bits of the 160-bit password hash
- unsigned char passwordDigest[20];
- SHA1((const unsigned char *)[password UTF8String], strlen([password UTF8String]), passwordDigest);
+ NSData *passwordDigest = [[password dataUsingEncoding:NSUTF8StringEncoding] sha1Hash];
AES_KEY aesKey;
- AES_set_encrypt_key(passwordDigest, 128, &aesKey);
+ AES_set_encrypt_key([passwordDigest bytes], 128, &aesKey);
// AES-128-cbc encrypt the data, filling in the buffer after the IV
AES_cbc_encrypt(paddedBytes, encryptedBytes + 16, paddedLength, &aesKey, iv, AES_ENCRYPT);
@@ -83,12 +112,11 @@
- (NSData *)dataDecryptedWithPassword:(NSString *)password
{
// Create the key from the password hash
- unsigned char passwordDigest[20];
- SHA1((const unsigned char *)[password UTF8String], strlen([password UTF8String]), passwordDigest);
+ NSData *passwordDigest = [[password dataUsingEncoding:NSUTF8StringEncoding] sha1Hash];
// AES-128-cbc decrypt the data
AES_KEY aesKey;
- AES_set_decrypt_key(passwordDigest, 128, &aesKey);
+ AES_set_decrypt_key([passwordDigest bytes], 128, &aesKey);
// Total length = encrypted length + IV
NSInteger totalLength = [self length];
@@ -312,3 +340,13 @@
}
@end
+
+#pragma mark -
+
+uint32_t LimitUInt32(NSUInteger i) {
+#if NSUIntegerMax > UINT32_MAX
+ return (i > UINT32_MAX)? UINT32_MAX : (uint32_t)i;
+#else
+ return i;
+#endif
+}