CocoaSecurity/CocoaSecurity/CocoaSecurity.m
2012-05-15 06:33:32 +08:00

505 lines
18 KiB
Objective-C

//
// CocoaSecurity.m
//
// Created by Kelp on 12/5/12.
// Copyright (c) 2012 Kelp http://kelp.phate.org/
//
#import "CocoaSecurity.h"
#pragma mark - CocoaSecurity
@implementation CocoaSecurity
#pragma mark - AES Encrypt
// default AES Encrypt, key -> SHA384(key).sub(0, 32), iv -> SHA384(key).sub(32, 16)
- (CocoaSecurityResult *)aesEncrypt:(NSString *)data key:(NSString *)key
{
CocoaSecurityResult * sha = [self sha384:key];
NSData *aesKey = [sha.data subdataWithRange:NSMakeRange(0, 32)];
NSData *aesIv = [sha.data subdataWithRange:NSMakeRange(32, 16)];
return [self aesEncrypt:data key:aesKey iv:aesIv];
}
#pragma mark AES Encrypt 128, 192, 256
- (CocoaSecurityResult *)aesEncrypt:(NSString *)data hexKey:(NSString *)key hexIv:(NSString *)iv
{
CocoaSecurityDecoder *decoder = [[CocoaSecurityDecoder alloc] init];
NSData *aesKey = [decoder hex:key];
NSData *aesIv = [decoder hex:iv];
[decoder release];
return [self aesEncrypt:data key:aesKey iv:aesIv];
}
- (CocoaSecurityResult *)aesEncrypt:(NSString *)data key:(NSData *)key iv:(NSData *)iv
{
return [self aesEncryptWithData:[data dataUsingEncoding:NSUTF8StringEncoding] key:key iv:iv];
}
- (CocoaSecurityResult *)aesEncryptWithData:(NSData *)data key:(NSData *)key iv:(NSData *)iv
{
// check length of key and iv
if ([iv length] != 16) {
@throw [NSException exceptionWithName:@"Cocoa Security"
reason:@"Length of iv is wrong. Length of iv should be 16(128bits)"
userInfo:nil];
}
if ([key length] != 16 && [key length] != 24 && [key length] != 32 ) {
@throw [NSException exceptionWithName:@"Cocoa Security"
reason:@"Length of key is wrong. Length of iv should be 16, 24 or 32(128, 192 or 256bits)"
userInfo:nil];
}
// setup output buffer
size_t bufferSize = [data length] + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
// do encrypt
size_t encryptedSize = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
[key bytes], // Key
[key length], // kCCKeySizeAES
[iv bytes], // IV
[data bytes],
[data length],
buffer,
bufferSize,
&encryptedSize);
if (cryptStatus == kCCSuccess) {
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:buffer length:encryptedSize] autorelease];
free(buffer);
return result;
} else {
free(buffer);
@throw [NSException exceptionWithName:@"Cocoa Security"
reason:@"Encrypt Error!"
userInfo:nil];
return nil;
}
}
#pragma mark AES Decrypt 128, 192, 256
// default AES Decrypt, key -> SHA384(key).sub(0, 32), iv -> SHA384(key).sub(32, 16)
- (CocoaSecurityResult *)aesDecryptWithBase64:(NSString *)data key:(NSString *)key
{
CocoaSecurityResult * sha = [self sha384:key];
NSData *aesKey = [sha.data subdataWithRange:NSMakeRange(0, 32)];
NSData *aesIv = [sha.data subdataWithRange:NSMakeRange(32, 16)];
return [self aesDecryptWithBase64:data key:aesKey iv:aesIv];
}
#pragma mark AES Encrypt 128, 192, 256
- (CocoaSecurityResult *)aesDecryptWithBase64:(NSString *)data hexKey:(NSString *)key hexIv:(NSString *)iv
{
CocoaSecurityDecoder *decoder = [[CocoaSecurityDecoder alloc] init];
NSData *aesKey = [decoder hex:key];
NSData *aesIv = [decoder hex:iv];
[decoder release];
return [self aesDecryptWithBase64:data key:aesKey iv:aesIv];
}
- (CocoaSecurityResult *)aesDecryptWithBase64:(NSString *)data key:(NSData *)key iv:(NSData *)iv
{
CocoaSecurityDecoder *decoder = [[[CocoaSecurityDecoder alloc] init] autorelease];
return [self aesDecryptWithData:[decoder base64:data] key:key iv:iv];
}
- (CocoaSecurityResult *)aesDecryptWithData:(NSData *)data key:(NSData *)key iv:(NSData *)iv
{
// check length of key and iv
if ([iv length] != 16) {
@throw [NSException exceptionWithName:@"Cocoa Security"
reason:@"Length of iv is wrong. Length of iv should be 16(128bits)"
userInfo:nil];
}
if ([key length] != 16 && [key length] != 24 && [key length] != 32 ) {
@throw [NSException exceptionWithName:@"Cocoa Security"
reason:@"Length of key is wrong. Length of iv should be 16, 24 or 32(128, 192 or 256bits)"
userInfo:nil];
}
// setup output buffer
size_t bufferSize = [data length] + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
// do encrypt
size_t encryptedSize = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
[key bytes], // Key
[key length], // kCCKeySizeAES
[iv bytes], // IV
[data bytes],
[data length],
buffer,
bufferSize,
&encryptedSize);
if (cryptStatus == kCCSuccess) {
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:buffer length:encryptedSize] autorelease];
free(buffer);
return result;
} else {
free(buffer);
@throw [NSException exceptionWithName:@"Cocoa Security"
reason:@"Decrypt Error!"
userInfo:nil];
return nil;
}
}
#pragma mark - MD5
- (CocoaSecurityResult *)md5:(NSString *)hashString
{
return [self md5WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]];
}
- (CocoaSecurityResult *)md5WithData:(NSData *)hashData
{
unsigned char *digest;
digest = malloc(CC_MD5_DIGEST_LENGTH);
CC_MD5([hashData bytes], [hashData length], digest);
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:digest length:CC_MD5_DIGEST_LENGTH] autorelease];
free(digest);
return result;
}
#pragma mark - HMAC-MD5
- (CocoaSecurityResult *)hmacMd5:(NSString *)hashString hmacKey:(NSString *)key
{
return [self hmacMd5WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key];
}
- (CocoaSecurityResult *)hmacMd5WithData:(NSData *)hashData hmacKey:(NSString *)key
{
unsigned char *digest;
digest = malloc(CC_MD5_DIGEST_LENGTH);
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
CCHmac(kCCHmacAlgMD5, cKey, strlen(cKey), [hashData bytes], [hashData length], digest);
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:digest length:CC_MD5_DIGEST_LENGTH] autorelease];
free(digest);
cKey = nil;
return result;
}
#pragma mark - SHA1
- (CocoaSecurityResult *)sha1:(NSString *)hashString
{
return [self sha1WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]];
}
- (CocoaSecurityResult *)sha1WithData:(NSData *)hashData
{
unsigned char *digest;
digest = malloc(CC_SHA1_DIGEST_LENGTH);
CC_SHA1([hashData bytes], [hashData length], digest);
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA1_DIGEST_LENGTH] autorelease];
free(digest);
return result;
}
#pragma mark SHA224
- (CocoaSecurityResult *)sha224:(NSString *)hashString
{
return [self sha224WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]];
}
- (CocoaSecurityResult *)sha224WithData:(NSData *)hashData
{
unsigned char *digest;
digest = malloc(CC_SHA224_DIGEST_LENGTH);
CC_SHA224([hashData bytes], [hashData length], digest);
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA224_DIGEST_LENGTH] autorelease];
free(digest);
return result;
}
#pragma mark SHA256
- (CocoaSecurityResult *)sha256:(NSString *)hashString
{
return [self sha256WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]];
}
- (CocoaSecurityResult *)sha256WithData:(NSData *)hashData
{
unsigned char *digest;
digest = malloc(CC_SHA256_DIGEST_LENGTH);
CC_SHA256([hashData bytes], [hashData length], digest);
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA256_DIGEST_LENGTH] autorelease];
free(digest);
return result;
}
#pragma mark SHA384
- (CocoaSecurityResult *)sha384:(NSString *)hashString
{
return [self sha384WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]];
}
- (CocoaSecurityResult *)sha384WithData:(NSData *)hashData
{
unsigned char *digest;
digest = malloc(CC_SHA384_DIGEST_LENGTH);
CC_SHA384([hashData bytes], [hashData length], digest);
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA384_DIGEST_LENGTH] autorelease];
free(digest);
return result;
}
#pragma mark SHA512
- (CocoaSecurityResult *)sha512:(NSString *)hashString
{
return [self sha512WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]];
}
- (CocoaSecurityResult *)sha512WithData:(NSData *)hashData
{
unsigned char *digest;
digest = malloc(CC_SHA512_DIGEST_LENGTH);
CC_SHA512([hashData bytes], [hashData length], digest);
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA512_DIGEST_LENGTH] autorelease];
free(digest);
return result;
}
#pragma mark - HMAC-SHA1
- (CocoaSecurityResult *)hmacSha1:(NSString *)hashString hmacKey:(NSString *)key
{
return [self hmacSha1WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key];
}
- (CocoaSecurityResult *)hmacSha1WithData:(NSData *)hashData hmacKey:(NSString *)key
{
unsigned char *digest;
digest = malloc(CC_SHA1_DIGEST_LENGTH);
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), [hashData bytes], [hashData length], digest);
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA1_DIGEST_LENGTH] autorelease];
free(digest);
cKey = nil;
return result;
}
#pragma mark HMAC-SHA224
- (CocoaSecurityResult *)hmacSha224:(NSString *)hashString hmacKey:(NSString *)key
{
return [self hmacSha224WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key];
}
- (CocoaSecurityResult *)hmacSha224WithData:(NSData *)hashData hmacKey:(NSString *)key
{
unsigned char *digest;
digest = malloc(CC_SHA224_DIGEST_LENGTH);
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
CCHmac(kCCHmacAlgSHA224, cKey, strlen(cKey), [hashData bytes], [hashData length], digest);
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA224_DIGEST_LENGTH] autorelease];
free(digest);
cKey = nil;
return result;
}
#pragma mark HMAC-SHA256
- (CocoaSecurityResult *)hmacSha256:(NSString *)hashString hmacKey:(NSString *)key
{
return [self hmacSha256WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key];
}
- (CocoaSecurityResult *)hmacSha256WithData:(NSData *)hashData hmacKey:(NSString *)key
{
unsigned char *digest;
digest = malloc(CC_SHA256_DIGEST_LENGTH);
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), [hashData bytes], [hashData length], digest);
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA256_DIGEST_LENGTH] autorelease];
free(digest);
cKey = nil;
return result;
}
#pragma mark HMAC-SHA384
- (CocoaSecurityResult *)hmacSha384:(NSString *)hashString hmacKey:(NSString *)key
{
return [self hmacSha384WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key];
}
- (CocoaSecurityResult *)hmacSha384WithData:(NSData *)hashData hmacKey:(NSString *)key
{
unsigned char *digest;
digest = malloc(CC_SHA384_DIGEST_LENGTH);
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
CCHmac(kCCHmacAlgSHA384, cKey, strlen(cKey), [hashData bytes], [hashData length], digest);
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA384_DIGEST_LENGTH] autorelease];
free(digest);
cKey = nil;
return result;
}
#pragma mark HMAC-SHA512
- (CocoaSecurityResult *)hmacSha512:(NSString *)hashString hmacKey:(NSString *)key
{
return [self hmacSha512WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key];
}
- (CocoaSecurityResult *)hmacSha512WithData:(NSData *)hashData hmacKey:(NSString *)key
{
unsigned char *digest;
digest = malloc(CC_SHA512_DIGEST_LENGTH);
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
CCHmac(kCCHmacAlgSHA512, cKey, strlen(cKey), [hashData bytes], [hashData length], digest);
CocoaSecurityResult *result = [[[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA512_DIGEST_LENGTH] autorelease];
free(digest);
cKey = nil;
return result;
}
@end
#pragma mark - CocoaSecurityResult
@implementation CocoaSecurityResult
- (id)initWithBytes: (unsigned char[])initData length: (uint) length
{
self.data = [NSData dataWithBytes:initData length:length];
return self;
}
#pragma mark - NSData
@synthesize data;
#pragma mark UTF8 String
// convert CocoaSecurityResult to UTF8 string
- (NSString *)utf8String
{
NSString *result = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
return result;
}
#pragma mark HEX
// convert CocoaSecurityResult to HEX string
- (NSString *)hex
{
CocoaSecurityEncoder *encoder = [[[CocoaSecurityEncoder alloc] init] autorelease];
return [encoder hex:data useLower:false];
}
- (NSString *)hexLower
{
CocoaSecurityEncoder *encoder = [[[CocoaSecurityEncoder alloc] init] autorelease];
return [encoder hex:data useLower:true];
}
#pragma mark Base64
// convert CocoaSecurityResult to Base64 string
- (NSString *)base64
{
CocoaSecurityEncoder *encoder = [[[CocoaSecurityEncoder alloc] init] autorelease];
return [encoder base64:data];
}
@end
#pragma mark - CocoaSecurityEncoder
@implementation CocoaSecurityEncoder
// convert NSData to Base64
- (NSString *)base64: (NSData *)data
{
// base on GTMBase64
NSString *result = [[NSString alloc] initWithData:[GTMBase64 encodeData:data] encoding:NSUTF8StringEncoding];
return [result autorelease];
}
// convert NSData to hex string
- (NSString *)hex: (NSData *)data useLower: (bool)isOutputLower
{
static const char HexEncodeCharsLower[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
static const char HexEncodeChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char *resultData;
// malloc result data
resultData = malloc([data length] * 2 +1);
// convert imgData(NSData) to char[]
unsigned char *sourceData = ((unsigned char *)[data bytes]);
uint length = [data length];
if (isOutputLower) {
for (uint index = 0; index < length; index++) {
// set result data
resultData[index * 2] = HexEncodeCharsLower[(sourceData[index] >> 4)];
resultData[index * 2 + 1] = HexEncodeCharsLower[(sourceData[index] % 0x10)];
}
}
else {
for (uint index = 0; index < length; index++) {
// set result data
resultData[index * 2] = HexEncodeChars[(sourceData[index] >> 4)];
resultData[index * 2 + 1] = HexEncodeChars[(sourceData[index] % 0x10)];
}
}
resultData[[data length] * 2] = 0;
// convert result(char[]) to NSString
NSString *result = [NSString stringWithCString:resultData encoding:NSASCIIStringEncoding];
sourceData = nil;
free(resultData);
return result;
}
@end
#pragma mark - CocoaSecurityDecoder
@implementation CocoaSecurityDecoder
- (NSData *)base64:(NSString *)data
{
// base on GTMBase64
NSData *result = [[NSData alloc] initWithData:[GTMBase64 decodeString:data]];
return [result autorelease];
}
- (NSData *)hex: (NSString *)data
{
static const unsigned char HexDecodeChars[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, //49
2, 3, 4, 5, 6, 7, 8, 9, 0, 0, //59
0, 0, 0, 0, 0, 10, 11, 12, 13, 14,
15, 0, 0, 0, 0, 0, 0, 0, 0, 0, //79
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 10, 11, 12, //99
13, 14, 15
};
// convert data(NSString) to CString
const char *source = [data cStringUsingEncoding:NSUTF8StringEncoding];
// malloc buffer
unsigned char *buffer;
uint length = strlen(source) / 2;
buffer = malloc(length);
for (uint index = 0; index < length; index++) {
buffer[index] = (HexDecodeChars[source[index * 2]] << 4) + (HexDecodeChars[source[index * 2 + 1]]);
}
// init result NSData
NSData *result = [NSData dataWithBytes:buffer length:length];
free(buffer);
source = nil;
return result;
}
@end