Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 63dca71e4b
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 112 lines (88 sloc) 3.199 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
//
// PKWebSocketCrypto.m
// PKWebSocket
//
// Created by Pavel Kunc on 17/04/2012.
// Copyright (c) 2012 Pavel Kunc. All rights reserved.
//

#import "PKWebSocketCrypto.h"

@implementation NSData (PKWebSocketCrypto)

- (NSData *)pk_MD5 {
    NSMutableData *digest = [NSMutableData dataWithLength:CC_MD5_DIGEST_LENGTH];
    CC_MD5([self bytes], (unsigned)[self length], [digest mutableBytes]);
    return (NSData *)digest;
}

- (NSData *)pk_SHA1 {
    NSMutableData *digest = [NSMutableData dataWithLength:CC_SHA1_DIGEST_LENGTH];
    CC_SHA1([self bytes], (unsigned)[self length], [digest mutableBytes]);
    return (NSData *)digest;
}

+ (NSData *)pk_randomBytesOfLength:(NSUInteger)aLength {
    NSMutableData *random = [NSMutableData dataWithLength:aLength];
    arc4random_buf([random mutableBytes], aLength);
    return (NSData *)random;
}

+ (NSData *)pk_hixie76ChallengeWithFirstKey:(SecKey)aKey1
                                  secondKey:(SecKey)aKey2
                                 randomData:(NSData *)aData {
    unsigned char bytes[8];
    pkws_hixie76ChallengeNumber(aKey1.num, &bytes[0]);
    pkws_hixie76ChallengeNumber(aKey2.num, &bytes[4]);
    NSMutableData *challenge = [NSMutableData dataWithBytes:bytes length:sizeof(bytes)];
    [challenge appendData:aData];
    return (NSData *)challenge;
}


@end


void pkws_hixie76ChallengeNumber(uint32_t number, unsigned char * buf) {
    unsigned char *p = buf + 3;
    for (int i = 0; i < 4; i++) {
        *p = number & 0xFF;
        --p;
        number >>= 8;
    }
}

SecKey pkws_hixie76Key() {
    struct SecKey seckey;
    uint32_t spaces, max, num, prod;
    unichar letter;
    NSInteger keylen;
    NSString *space = @" ";

    // As per 5.2.6, abort if numbers is not an integral multiple of spaces
    NSMutableString *key;
    do {
        spaces = (arc4random() % 12) + 1;
        // As per 5.2.5, abort the connection if spaces are zero.
        assert(spaces > 0 && spaces <= 12);

        max = (arc4random() % 4294967295U) / spaces;
        assert(max >= 0 && max <= 4294967295U);

        num = arc4random() % max;
        assert(num >= 0 && num <= max);

        prod = spaces * num;

        key = [NSMutableString stringWithFormat:@"%u", prod];
        keylen = [key length];
    } while (keylen % spaces != 0);

    // As per 4.1.21
    // Insert between one and twelve random characters from the ranges
    // U+0021 to U+002F and U+003A to U+007E into /key_1/ at random
    // positions.
    //
    // We choose 12
    for (NSUInteger i = 0; i < 12; i++) {
        if ((arc4random() % 2) == 0) {
            letter = (arc4random() % (47 - 33 + 1)) + 33;
        } else {
            letter = (arc4random() % (126 - 58 + 1)) + 58;
        }

        NSUInteger index = (arc4random() % (keylen-1));
        NSString *letterString = [[NSString alloc] initWithCharacters:&letter length:1];
        [key insertString:letterString atIndex:index];
    }

    keylen = [key length];

    for (NSUInteger i = 0; i < spaces; i++) {
        NSUInteger index = ((arc4random() % (keylen-2))+1);
        [key insertString:space atIndex:index];
    }

    seckey.num = num;
    seckey.key = key;

    return seckey;
}

Something went wrong with that request. Please try again.