Skip to content
This repository has been archived by the owner on Jan 17, 2023. It is now read-only.

Commit

Permalink
Authorization (draft) first done
Browse files Browse the repository at this point in the history
  • Loading branch information
Guilherme Vieira committed Jan 30, 2013
1 parent 25b17c9 commit 616edac
Showing 1 changed file with 74 additions and 2 deletions.
76 changes: 74 additions & 2 deletions AFAmazonS3Client/AFAmazonS3Client.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,65 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#import <CommonCrypto/CommonHMAC.h>
#import "AFAmazonS3Client.h"
#import "AFXMLRequestOperation.h"

NSString * const kAFAmazonS3BaseURLString = @"https://s3.amazonaws.com";
NSString * const kAFAmazonS3BucketBaseURLFormatString = @"https://%@.s3.amazonaws.com";
NSString * const kAFAmazonS3BaseURLString = @"http://s3.amazonaws.com";
NSString * const kAFAmazonS3BucketBaseURLFormatString = @"http://%@.s3.amazonaws.com";

static NSData * AFHMACSHA1EncodedDataFromStringWithKey(NSString *string, NSString *key) {
NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding];
CCHmacContext context;
const char *keyCString = [key cStringUsingEncoding:NSASCIIStringEncoding];

CCHmacInit(&context, kCCHmacAlgSHA1, keyCString, strlen(keyCString));
CCHmacUpdate(&context, [data bytes], [data length]);

unsigned char digestRaw[CC_SHA1_DIGEST_LENGTH];
NSInteger digestLength = CC_SHA1_DIGEST_LENGTH;

CCHmacFinal(&context, digestRaw);

return [NSData dataWithBytes:digestRaw length:digestLength];
}

static NSString *AFRFC822FormatStringFromDate(NSDate *date) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
[dateFormatter setDateFormat:@"EEE, dd MMM yyyy HH:mm:ss z"];
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]];

This comment has been minimized.

Copy link
@mattt

mattt Feb 6, 2013

Contributor

FWIW, Apple suggests using en_US_POSIX as the locale when parsing, so I've gotten in the habit of using that for string representations as well.


return [dateFormatter stringFromDate:date];
}

NSString * AFBase64EncodedStringFromData(NSData *data) {
NSUInteger length = [data length];
NSMutableData *mutableData = [NSMutableData dataWithLength:((length + 2) / 3) * 4];

uint8_t *input = (uint8_t *)[data bytes];
uint8_t *output = (uint8_t *)[mutableData mutableBytes];

for (NSUInteger i = 0; i < length; i += 3) {
NSUInteger value = 0;
for (NSUInteger j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}

static uint8_t const kAFBase64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

NSUInteger idx = (i / 3) * 4;
output[idx + 0] = kAFBase64EncodingTable[(value >> 18) & 0x3F];
output[idx + 1] = kAFBase64EncodingTable[(value >> 12) & 0x3F];
output[idx + 2] = (i + 1) < length ? kAFBase64EncodingTable[(value >> 6) & 0x3F] : '=';
output[idx + 3] = (i + 2) < length ? kAFBase64EncodingTable[(value >> 0) & 0x3F] : '=';
}

return [[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding];
}

#pragma mark -

Expand Down Expand Up @@ -260,4 +314,22 @@ - (void)setObjectWithMethod:(NSString *)method
}
}

- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
path:(NSString *)path
parameters:(NSDictionary *)parameters
{
NSMutableURLRequest *request = [super requestWithMethod:method path:path parameters:parameters];

NSString *canonicalizedResource = [NSString stringWithFormat:@"/%@%@", _bucket, path];
NSString *date = AFRFC822FormatStringFromDate([NSDate date]);
NSString *stringToSign = [NSString stringWithFormat:@"%@\n\n\n%@\n%@", method, date, canonicalizedResource];
NSData *hmac = AFHMACSHA1EncodedDataFromStringWithKey(stringToSign, _secret);
NSString *signature = AFBase64EncodedStringFromData(hmac);

[request setValue:date forHTTPHeaderField:@"Date"];
[request setValue:[NSString stringWithFormat:@"AWS %@:%@", _accessKey, signature] forHTTPHeaderField:@"Authorization"];

This comment has been minimized.

Copy link
@mattt

mattt Feb 6, 2013

Contributor

There should probably be a check for access key / secret, since -initWithBaseURL: is still a valid initializer.


return request;
}

@end

2 comments on commit 616edac

@mattt
Copy link
Contributor

@mattt mattt commented on 616edac Feb 6, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a really nice, clean implementation. Nice work! I'd love to get this merged in as soon as possible.

@gvieira
Copy link

@gvieira gvieira commented on 616edac May 1, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mattt Sure! I'll make the adjustments you suggested right now. Thanks for your feedback. It really means to me to hear from you!

BTW, sorry for the late response. I was expecting Github to send me an email telling me you've reviewed my code.

Please sign in to comment.