Skip to content

Commit

Permalink
Hide OpenSSL headers in private module
Browse files Browse the repository at this point in the history
  • Loading branch information
kishikawakatsumi committed Feb 9, 2018
1 parent 5442608 commit 33521ba
Show file tree
Hide file tree
Showing 21 changed files with 297 additions and 353 deletions.
22 changes: 15 additions & 7 deletions BitcoinKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
1419E83A202CDBE500FCB0BE /* BitcoinKitInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1419E838202CDBE500FCB0BE /* BitcoinKitInternal.h */; };
1419E83B202CDBE500FCB0BE /* BitcoinKitInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = 1419E839202CDBE500FCB0BE /* BitcoinKitInternal.m */; };
141FE2E22022588C00A08B04 /* PublicKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 141FE2E12022588C00A08B04 /* PublicKey.swift */; };
141FE2E42022589E00A08B04 /* PrivateKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 141FE2E32022589E00A08B04 /* PrivateKey.swift */; };
1463E6B42025E9480033DAAE /* BlockStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1463E6B32025E9480033DAAE /* BlockStore.swift */; };
Expand Down Expand Up @@ -47,6 +49,8 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
1419E838202CDBE500FCB0BE /* BitcoinKitInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BitcoinKitInternal.h; sourceTree = "<group>"; };
1419E839202CDBE500FCB0BE /* BitcoinKitInternal.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BitcoinKitInternal.m; sourceTree = "<group>"; };
141FE2E12022588C00A08B04 /* PublicKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicKey.swift; sourceTree = "<group>"; };
141FE2E32022589E00A08B04 /* PrivateKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateKey.swift; sourceTree = "<group>"; };
1463E6B32025E9480033DAAE /* BlockStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockStore.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -144,6 +148,8 @@
147F9728201FC89E0071F49D /* BloomFilter.swift */,
147494ED201FADAC006D1CF8 /* MurmurHash.swift */,
14CDC38B2021EF5000C01556 /* Helpers.swift */,
1419E838202CDBE500FCB0BE /* BitcoinKitInternal.h */,
1419E839202CDBE500FCB0BE /* BitcoinKitInternal.m */,
147494CB201F9A29006D1CF8 /* Info.plist */,
);
path = BitcoinKit;
Expand All @@ -166,6 +172,7 @@
buildActionMask = 2147483647;
files = (
147494D8201F9A29006D1CF8 /* BitcoinKit.h in Headers */,
1419E83A202CDBE500FCB0BE /* BitcoinKitInternal.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -279,7 +286,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if [ ! -d \"$SRCROOT/Libraries/secp256k1/lib\" ] || [ ! -d \"$SRCROOT/Libraries/crypto/lib\" ]; then\n env -i PATH=$PATH sh \"$SRCROOT/setup/build_libraries.sh\"\nfi\n";
shellScript = "if [ ! -d \"$SRCROOT/Libraries/secp256k1/lib\" ] || [ ! -d \"$SRCROOT/Libraries/openssl/lib\" ]; then\n env -i PATH=$PATH sh \"$SRCROOT/setup/build_libraries.sh\"\nfi\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
Expand All @@ -302,6 +309,7 @@
14CDC3862021824200C01556 /* Wallet.swift in Sources */,
141FE2E42022589E00A08B04 /* PrivateKey.swift in Sources */,
14CDC38C2021EF5000C01556 /* Helpers.swift in Sources */,
1419E83B202CDBE500FCB0BE /* BitcoinKitInternal.m in Sources */,
147494F0201FAE30006D1CF8 /* Serialization.swift in Sources */,
147494E4201F9B85006D1CF8 /* Crypto.swift in Sources */,
1463E6B62025E99C0033DAAE /* BlockChain.swift in Sources */,
Expand Down Expand Up @@ -389,7 +397,6 @@
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_INCLUDE_PATHS = "$(SRCROOT)/Libraries";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
Expand Down Expand Up @@ -442,7 +449,6 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_INCLUDE_PATHS = "$(SRCROOT)/Libraries";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
Expand All @@ -463,19 +469,20 @@
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
HEADER_SEARCH_PATHS = (
"$(SRCROOT)/Libraries/crypto/include",
"$(SRCROOT)/Libraries/openssl/include",
"$(SRCROOT)/Libraries/secp256k1/include",
);
INFOPLIST_FILE = BitcoinKit/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(SRCROOT)/Libraries/crypto/lib",
"$(SRCROOT)/Libraries/openssl/lib",
"$(SRCROOT)/Libraries/secp256k1/lib",
);
PRODUCT_BUNDLE_IDENTIFIER = com.kishikawakatsumi.BitcoinKit;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_INCLUDE_PATHS = "$(SRCROOT)/Libraries $(SRCROOT)/BitcoinKit/BitcoinKitInternal";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
Expand All @@ -495,19 +502,20 @@
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
HEADER_SEARCH_PATHS = (
"$(SRCROOT)/Libraries/crypto/include",
"$(SRCROOT)/Libraries/openssl/include",
"$(SRCROOT)/Libraries/secp256k1/include",
);
INFOPLIST_FILE = BitcoinKit/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(SRCROOT)/Libraries/crypto/lib",
"$(SRCROOT)/Libraries/openssl/lib",
"$(SRCROOT)/Libraries/secp256k1/lib",
);
PRODUCT_BUNDLE_IDENTIFIER = com.kishikawakatsumi.BitcoinKit;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_INCLUDE_PATHS = "$(SRCROOT)/Libraries $(SRCROOT)/BitcoinKit/BitcoinKitInternal";
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
Expand Down
24 changes: 24 additions & 0 deletions BitcoinKit/BitcoinKitInternal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// OpenSSL.h
// BitcoinKit
//
// Created by kishikawakatsumi on 2018/02/09.
// Copyright © 2018 Kishikawa Katsumi. All rights reserved.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN
@interface BitcoinKitInternal : NSObject

+ (NSData *)sha256:(NSData *)data;
+ (NSData *)ripemd160:(NSData *)data;
+ (NSData *)hmacsha512:(NSData *)data key:(NSData *)key;

+ (NSData *)computePublicKeyFromPrivateKey:(NSData *)privateKey compression:(BOOL)compression;

+ (NSData *)deriveKey:(NSData *)password salt:(NSData *)salt iterations:(NSInteger)iterations keyLength:(NSInteger)keyLength;
+ (nullable NSArray<NSData *> *)deriveKey:(nullable NSData *)privateKey publicKey:(NSData *)publicKey chainCode:(NSData *)chainCode atIndex:(uint32_t)index hardened:(BOOL)hardened;

@end
NS_ASSUME_NONNULL_END
154 changes: 154 additions & 0 deletions BitcoinKit/BitcoinKitInternal.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
//
// OpenSSL.m
// BitcoinKit
//
// Created by kishikawakatsumi on 2018/02/09.
// Copyright © 2018 Kishikawa Katsumi. All rights reserved.
//

#import "BitcoinKitInternal.h"
#import <openssl/sha.h>
#import <openssl/ripemd.h>
#import <openssl/hmac.h>
#import <openssl/ec.h>

@implementation BitcoinKitInternal

+ (NSData *)sha256:(NSData *)data {
NSMutableData *result = [NSMutableData dataWithLength:SHA256_DIGEST_LENGTH];
SHA256(data.bytes, data.length, result.mutableBytes);
return result;
}

+ (NSData *)ripemd160:(NSData *)data {
NSMutableData *result = [NSMutableData dataWithLength:RIPEMD160_DIGEST_LENGTH];
RIPEMD160(data.bytes, data.length, result.mutableBytes);
return result;
}

+ (NSData *)hmacsha512:(NSData *)data key:(NSData *)key {
unsigned int length = SHA512_DIGEST_LENGTH;
NSMutableData *result = [NSMutableData dataWithLength:length];
HMAC(EVP_sha512(), key.bytes, (int)key.length, data.bytes, data.length, result.mutableBytes, &length);
return result;
}

+ (NSData *)generatePrivateKey {
return [NSData data];
}

+ (NSData *)computePublicKeyFromPrivateKey:(NSData *)privateKey compression:(BOOL)compression {
BN_CTX *ctx = BN_CTX_new();
EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp256k1);
const EC_GROUP *group = EC_KEY_get0_group(key);

BIGNUM *prv = BN_new();
BN_bin2bn(privateKey.bytes, (int)privateKey.length, prv);

EC_POINT *pub = EC_POINT_new(group);
EC_POINT_mul(group, pub, prv, nil, nil, ctx);
EC_KEY_set_private_key(key, prv);
EC_KEY_set_public_key(key, pub);

NSMutableData *result;
if (compression) {
EC_KEY_set_conv_form(key, POINT_CONVERSION_COMPRESSED);
unsigned char *bytes = NULL;
int length = i2o_ECPublicKey(key, &bytes);
result = [NSMutableData dataWithBytesNoCopy:bytes length:length];
} else {
result = [NSMutableData dataWithLength:65];
BIGNUM *n = BN_new();
EC_POINT_point2bn(group, pub, POINT_CONVERSION_UNCOMPRESSED, n, ctx);
BN_bn2bin(n, result.mutableBytes);
BN_free(n);
}

BN_free(prv);
EC_POINT_free(pub);
EC_KEY_free(key);
BN_CTX_free(ctx);

return result;
}

+ (NSData *)deriveKey:(NSData *)password salt:(NSData *)salt iterations:(NSInteger)iterations keyLength:(NSInteger)keyLength {
NSMutableData *result = [NSMutableData dataWithLength:keyLength];
PKCS5_PBKDF2_HMAC(password.bytes, (int)password.length, salt.bytes, (int)salt.length, (int)iterations, EVP_sha512(), (int)keyLength, result.mutableBytes);
return result;
}

+ (NSArray *)deriveKey:(nullable NSData *)privateKey publicKey:(NSData *)publicKey chainCode:(NSData *)chainCode atIndex:(uint32_t)index hardened:(BOOL)hardened {
BN_CTX *ctx = BN_CTX_new();

NSMutableData *data = [NSMutableData data];
if (hardened) {
uint8_t padding = 0;
[data appendBytes:&padding length:1];
[data appendData:privateKey];
} else {
[data appendData:publicKey];
}

uint32_t i = OSSwapHostToBigInt32(hardened ? (0x80000000 | index) : index);
[data appendBytes:&i length:sizeof(i)];

NSData *digest = [self hmacsha512:data key:chainCode];
NSData *prv = [digest subdataWithRange:NSMakeRange(0, 32)];
NSData *derivedChainCode = [digest subdataWithRange:NSMakeRange(32, 32)];

BIGNUM *curveOrder = BN_new();
BN_hex2bn(&curveOrder, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");

BIGNUM *factor = BN_new();
BN_bin2bn(prv.bytes, (int)prv.length, factor);
if (BN_cmp(factor, curveOrder) < 0) {
return nil;
}

NSMutableData *result;
if (privateKey) {
BIGNUM *pkNum = BN_new();
BN_bin2bn(privateKey.bytes, (int)privateKey.length, pkNum);

BN_mod_add(pkNum, pkNum, factor, curveOrder, ctx);
if (BN_is_zero(pkNum)) {
return nil;
}

int numBytes = BN_num_bytes(pkNum);
result = [NSMutableData dataWithLength:numBytes];
BN_bn2bin(pkNum, result.mutableBytes);

BN_free(pkNum);
} else {
BIGNUM *pubNum = BN_new();
BN_bin2bn(publicKey.bytes, (int)publicKey.length, pubNum);
EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp256k1);

EC_POINT *point = EC_POINT_new(group);
EC_POINT_bn2point(group, pubNum, point, ctx);
EC_POINT_mul(group, point, factor, point, BN_value_one(), ctx);
if (EC_POINT_is_at_infinity(group, point) == 0) {
return nil;
}

BIGNUM *pointNum = BN_new();
result = [NSMutableData dataWithLength:33];

EC_POINT_point2bn(group, point, POINT_CONVERSION_COMPRESSED, pointNum, ctx);
BN_bn2bin(pointNum, result.mutableBytes);

BN_free(pointNum);
EC_POINT_free(point);
EC_GROUP_free(group);
}

BN_free(factor);
BN_free(curveOrder);
BN_CTX_free(ctx);

return @[result, derivedChainCode];
}

@end
4 changes: 4 additions & 0 deletions BitcoinKit/BitcoinKitInternal/module.modulemap
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module BitcoinKitInternal {
header "../BitcoinKitInternal.h"
link "crypto"
}
35 changes: 11 additions & 24 deletions BitcoinKit/Crypto.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,28 @@
//

import Foundation
import crypto
import BitcoinKitInternal
import secp256k1

public struct Crypto {
public static func sha256(_ plain: Data) -> Data {
let length = Int(SHA256_DIGEST_LENGTH)
var result = [UInt8](repeating: 0, count: length)
_ = plain.withUnsafeBytes { SHA256($0, plain.count, &result) }
return Data(bytes: result, count: length)
public static func sha256(_ data: Data) -> Data {
return BitcoinKitInternal.sha256(data)
}

public static func sha256sha256(_ plain: Data) -> Data {
return sha256(sha256(plain))
public static func sha256sha256(_ data: Data) -> Data {
return sha256(sha256(data))
}

public static func ripemd160(_ plain: Data) -> Data {
let length = Int(RIPEMD160_DIGEST_LENGTH)
var result = [UInt8](repeating: 0, count: length)
_ = plain.withUnsafeBytes { RIPEMD160($0, plain.count, &result) }
return Data(bytes: result, count: length)
public static func ripemd160(_ data: Data) -> Data {
return BitcoinKitInternal.ripemd160(data)
}

public static func sha256ripemd160(_ plain: Data) -> Data {
return ripemd160(sha256(plain))
public static func sha256ripemd160(_ data: Data) -> Data {
return ripemd160(sha256(data))
}

public static func hmacsha512(key: Data, data: Data) -> Data {
var length = UInt32(SHA512_DIGEST_LENGTH)
var result = [UInt8](repeating: 0, count: Int(length))
_ = key.withUnsafeBytes { (keyPtr) in
data.withUnsafeBytes { (dataPtr) in
HMAC(EVP_sha512(), keyPtr, Int32(key.count), dataPtr, data.count, &result, &length)
}
}
return Data(result)
public static func hmacsha512(data: Data, key: Data) -> Data {
return BitcoinKitInternal.hmacsha512(data, key: key)
}

public static func sign(_ data: Data, privateKey: PrivateKey) throws -> Data {
Expand Down
Loading

0 comments on commit 33521ba

Please sign in to comment.