#include #include #include #include #include #include #include #include #include #include #include #include #include "RNDecryptor.h" #include "RNEncryptor.h" #include "NSData+CommonCrypto.h" #include "KeychainItemWrapper.h" CryptoHelper *helperInstance = nil; FILE *f; //Used for printing out BN stuff #define PRIVATE_KEY (__bridge id)kSecAttrAccount #define PUBLIC_KEY (__bridge id)kSecValueData #define ECDH_SIZE 256 static void *KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen) { #ifndef OPENSSL_NO_SHA if (*outlen < SHA_DIGEST_LENGTH) return NULL; else *outlen = SHA_DIGEST_LENGTH; void *sha1 = SHA1(in, inlen, out); NSData *data = [[NSData alloc] initWithBytes:(char *)in length:inlen]; NSLog(@"Encoded :: %@", [data base64EncodedString]); out = (void *)in; return (void *)inlen; return sha1; #else return NULL; #endif } #pragma mark - Secret Helper Methods! - (EC_POINT *)getPointFromX:(char *)x andY:(char *)y andGroup:(EC_GROUP *)ec_group { EC_POINT *new_point = EC_POINT_new(ec_group); BIGNUM *x_coord = BN_new(); BIGNUM *y_coord = BN_new(); BN_hex2bn(&x_coord, x); BN_hex2bn(&y_coord, y); EC_POINT_set_affine_coordinates_GFp(ec_group, new_point, x_coord, y_coord, NULL); return new_point; } - (BIGNUM *)bnFromString:(char *)str { BIGNUM *b = BN_new(); BN_hex2bn(&b, str); return b; } - (void)printBN:(const BIGNUM *)bn withTitle:(char *)title { printf("%s :: ", title); BN_print_fp(f, bn); printf("\n"); } - (NSData *)computeSharedKey:(EC_POINT *)otherPublicKey andPrivateKey:(EC_KEY *)privateKey { int alen = 0; int aout = 0; static const int KDF1_SHA1_len = 256; unsigned char *abuf = NULL; alen = KDF1_SHA1_len; abuf = (unsigned char *) OPENSSL_malloc (alen); aout = ECDH_compute_key(abuf, alen, otherPublicKey, privateKey, NULL); NSData *data = [[NSData alloc] initWithBytes:abuf length:aout]; NSLog(@"Data : %@", data); NSLog(@"Data length : %d", data.length); if(abuf) free(abuf); return data; } - (void)regenerateKeys { self.sharedKey = nil; self.privateKey = nil; SSL_library_init(); SSL_load_error_strings(); EC_KEY *ecdh = NULL; const EC_GROUP *group = NULL; OpenSSL_add_all_ciphers(); OpenSSL_add_all_algorithms(); //Generate Public ecdh = EC_KEY_new_by_curve_name(NID_secp256k1); EC_KEY_generate_key(ecdh); group = EC_KEY_get0_group(ecdh); BIGNUM *x = BN_new(); BIGNUM *y = BN_new(); EC_POINT_get_affine_coordinates_GFp(group, EC_KEY_get0_public_key(ecdh), x, y, NULL); char *xString = BN_bn2hex(x); char *yString = BN_bn2hex(y); char *privateString = BN_bn2hex(EC_KEY_get0_private_key(ecdh)); self.publicX = [[NSString alloc] initWithCString:xString encoding:NSUTF8StringEncoding]; self.publicY = [[NSString alloc] initWithCString:yString encoding:NSUTF8StringEncoding]; self.privateKey = [[NSString alloc] initWithCString:privateString encoding:NSUTF8StringEncoding]; [self.keychain setObject:[@{@"publicX" : self.publicX, @"publicY" : self.publicY} description] forKey:PUBLIC_KEY]; [self.keychain setObject:self.privateKey forKey:PRIVATE_KEY]; NSLog(@"Public X : %@", self.publicX); NSLog(@"Public Y : %@", self.publicY); NSLog(@"Private Key : %@", self.privateKey); } - (void)setSharedWithX:(NSString *)x andY:(NSString *)y { const char *xString = [x cStringUsingEncoding:NSUTF8StringEncoding]; const char *yString = [y cStringUsingEncoding:NSUTF8StringEncoding]; EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_secp256k1); const BIGNUM *privatKey = [self bnFromString:(char *)[self.privateKey cStringUsingEncoding:NSUTF8StringEncoding]]; const EC_POINT *publicKey = [self getPointFromX:(char *)[self.publicX cStringUsingEncoding:NSUTF8StringEncoding] andY:(char *)[self.publicY cStringUsingEncoding:NSUTF8StringEncoding] andGroup:(EC_GROUP *)EC_KEY_get0_group(ecdh)]; EC_POINT *otherPublic = [self getPointFromX:(char *)xString andY:(char *)yString andGroup:(EC_GROUP *)EC_KEY_get0_group(ecdh)]; EC_KEY_set_private_key(ecdh, privatKey); EC_KEY_set_public_key(ecdh, publicKey); self.sharedKey = [self computeSharedKey:otherPublic andPrivateKey:ecdh]; NSLog(@"%@", [self.sharedKey base64EncodedString]); NSLog(@"shared :: %@", [self.sharedKey base64EncodedString]); // EC_POINT_free(otherPublic); EC_KEY_free(ecdh); }