Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ddde4c7
commit 5e28b8f
Showing
2 changed files
with
205 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// | ||
// KSSHA1Stream.h | ||
// Sandvox | ||
// | ||
// Created by Mike on 12/03/2011. | ||
// Copyright 2011 Karelia Software. All rights reserved. | ||
// | ||
|
||
#import <Cocoa/Cocoa.h> | ||
#import <CommonCrypto/CommonDigest.h> | ||
|
||
|
||
|
||
@interface KSSHA1Stream : NSOutputStream | ||
{ | ||
@private | ||
CC_SHA1_CTX _ctx; | ||
NSData *_digest; | ||
} | ||
|
||
// nil until you call -close | ||
@property(nonatomic, copy, readonly) NSData *SHA1Digest; | ||
|
||
@end | ||
|
||
|
||
@interface KSSHA1Stream (KSURLHashing) | ||
+ (NSData *)SHA1DigestOfContentsOfURL:(NSURL *)URL; | ||
@end | ||
|
||
|
||
#pragma mark - | ||
|
||
|
||
@interface NSData (KSSHA1Stream) | ||
|
||
// Cryptographic hashes | ||
- (NSData *)ks_SHA1Digest; | ||
- (NSString *)ks_SHA1DigestString; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
// | ||
// KSSHA1Stream.m | ||
// Sandvox | ||
// | ||
// Created by Mike on 12/03/2011. | ||
// Copyright 2011 Karelia Software. All rights reserved. | ||
// | ||
|
||
#import "KSSHA1Stream.h" | ||
|
||
|
||
@implementation KSSHA1Stream | ||
|
||
- (id)init; | ||
{ | ||
[super init]; | ||
CC_SHA1_Init(&_ctx); | ||
return self; | ||
} | ||
|
||
- (void)close; | ||
{ | ||
unsigned char digest[CC_SHA1_DIGEST_LENGTH]; | ||
CC_SHA1_Final(digest, &_ctx); | ||
|
||
_digest = [[NSData alloc] initWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]; | ||
} | ||
|
||
- (void)dealloc; | ||
{ | ||
[_digest release]; | ||
[super dealloc]; | ||
} | ||
|
||
- (NSInteger)write:(const uint8_t *)buffer maxLength:(NSUInteger)len; | ||
{ | ||
CC_SHA1_Update(&_ctx, buffer, len); | ||
return len; | ||
} | ||
|
||
@synthesize SHA1Digest = _digest; | ||
|
||
@end | ||
|
||
|
||
#pragma mark - | ||
|
||
|
||
@implementation NSData (KSSHA1Stream) | ||
|
||
- (NSData *)ks_SHA1Digest | ||
{ | ||
KSSHA1Stream *stream = [[KSSHA1Stream alloc] init]; | ||
[stream write:[self bytes] maxLength:[self length]]; | ||
[stream close]; | ||
NSData *result = [[[stream SHA1Digest] copy] autorelease]; | ||
|
||
[stream release]; | ||
return result; | ||
} | ||
|
||
- (NSString *)ks_SHA1DigestString | ||
{ | ||
static char sHEHexDigits[] = "0123456789abcdef"; | ||
|
||
NSData *digestData = [self ks_SHA1Digest]; | ||
unsigned char *digest = (unsigned char *)[digestData bytes]; | ||
|
||
unsigned char digestString[2 * CC_SHA1_DIGEST_LENGTH]; | ||
NSUInteger i; | ||
for (i=0; i<CC_SHA1_DIGEST_LENGTH; i++) | ||
{ | ||
digestString[2*i] = sHEHexDigits[digest[i] >> 4]; | ||
digestString[2*i+1] = sHEHexDigits[digest[i] & 0x0f]; | ||
} | ||
|
||
return [[[NSString alloc] initWithBytes:(const char *)digestString | ||
length:2 * CC_SHA1_DIGEST_LENGTH | ||
encoding:NSASCIIStringEncoding] autorelease]; | ||
} | ||
|
||
@end | ||
|
||
|
||
#pragma mark - | ||
|
||
|
||
@implementation KSSHA1Stream (KSURLHashing) | ||
|
||
+ (NSData *)SHA1DigestOfContentsOfURL:(NSURL *)URL; | ||
{ | ||
OBPRECONDITION(URL); | ||
KSSHA1Stream *hasher = [[KSSHA1Stream alloc] initWithURL:URL]; | ||
|
||
NSData *result; | ||
if ([URL isFileURL]) | ||
{ | ||
NSInputStream *stream = [[NSInputStream alloc] initWithFileAtPath:[URL path]]; | ||
[stream open]; | ||
|
||
#define READ_BUFFER_SIZE 64*CC_SHA1_BLOCK_BYTES | ||
uint8_t buffer[READ_BUFFER_SIZE]; | ||
|
||
while ([stream streamStatus] < NSStreamStatusAtEnd) | ||
{ | ||
NSInteger length = [stream read:buffer maxLength:READ_BUFFER_SIZE]; | ||
|
||
if (length > 0) | ||
{ | ||
NSInteger written = [hasher write:buffer maxLength:length]; | ||
OBASSERT(written == length); | ||
} | ||
} | ||
|
||
[stream release]; | ||
|
||
[hasher close]; | ||
result = [hasher SHA1Digest]; | ||
} | ||
else | ||
{ | ||
// Run the runloop until done | ||
while (!(result = [hasher SHA1Digest])) | ||
{ | ||
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantPast]]; | ||
} | ||
|
||
// Finish up. Empty hash means load failed | ||
if (![result length]) result = nil; | ||
} | ||
|
||
|
||
// Finish up. Empty hash means load failed | ||
result = [[result copy] autorelease]; | ||
[hasher release]; | ||
return result; | ||
} | ||
|
||
- (id)initWithURL:(NSURL *)URL; | ||
{ | ||
[self init]; | ||
|
||
[NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:URL] | ||
delegate:self]; | ||
|
||
return self; | ||
} | ||
|
||
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data | ||
{ | ||
[self write:[data bytes] maxLength:[data length]]; | ||
} | ||
|
||
- (void)connectionDidFinishLoading:(NSURLConnection *)connection | ||
{ | ||
[self close]; | ||
} | ||
|
||
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error | ||
{ | ||
_digest = [[NSData alloc] init]; | ||
} | ||
|
||
@end |