Remove CryptoSwift add CryptoKit. Bump OS Versions

This commit is contained in:
Francisco Gindre 2020-02-27 20:15:57 -03:00
parent 8e61453f48
commit 133e80df35
8 changed files with 232 additions and 148 deletions

View File

@ -1 +0,0 @@
github "krzyzanowskim/CryptoSwift" ~> 0.14.0

View File

@ -1 +0,0 @@
github "krzyzanowskim/CryptoSwift" "0.14.0"

View File

@ -13,12 +13,11 @@
s.author = { "Keefer Taylor" => "keefer@keefertaylor.com" }
s.source = { :git => "https://github.com/keefertaylor/MnemonicKit.git", :tag => "1.3.10" }
s.source_files = "MnemonicKit/**/*.swift",
s.swift_version = "4.2"
s.ios.deployment_target = "8.0"
s.osx.deployment_target = "10.10"
s.dependency "CryptoSwift", "~> 0.14.0"
s.swift_version = "5.1"
s.ios.deployment_target = "13.0"
s.osx.deployment_target = "10.15"
s.framework = "CryptoKit"
s.test_spec "Tests" do |test_spec|
test_spec.source_files = "Tests/*.swift"
test_spec.resources = ["Tests/*.json"]

View File

@ -7,11 +7,11 @@
objects = {
/* Begin PBXBuildFile section */
0DDAF3A42408728600EA9427 /* PKC5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DDAF3A32408728600EA9427 /* PKC5.swift */; };
0DDAF3A52408728600EA9427 /* PKC5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DDAF3A32408728600EA9427 /* PKC5.swift */; };
122777029525BA9CC4F9A958 /* Mnemonic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12B9024EB02AB18E1F44789A /* Mnemonic.swift */; };
2A51344C2F30A6CE1A391BCF /* MnemonicKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A5EC633D7524CD344B44513 /* MnemonicKitTests.swift */; };
2C9FBE1A25B2CA86DB509726 /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BA1EBAC8ABDF9E72ABA1B642 /* CryptoSwift.framework */; };
422A84796316566997821D77 /* vectors.json in Resources */ = {isa = PBXBuildFile; fileRef = C3E5287598681E0527694214 /* vectors.json */; };
59FE4CF322226154B9B687CE /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8871A4FF644B8E4F13723E6 /* CryptoSwift.framework */; };
5A11F552AAEA9E58CE8CC50D /* CryptoSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F8871A4FF644B8E4F13723E6 /* CryptoSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
81D18E658D26212E4D7647D8 /* String+MnemonicData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 256E6CB62D82160ACBA1512E /* String+MnemonicData.swift */; };
8DC3D3DA23DBEAD93257DE4F /* MnemonicKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC7EE929BD11BA8AB38F9C19 /* MnemonicKit.framework */; };
@ -78,6 +78,7 @@
/* Begin PBXFileReference section */
0A5E025936BA30D49D80AF51 /* Chinese.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Chinese.swift; sourceTree = "<group>"; };
0A5EC633D7524CD344B44513 /* MnemonicKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MnemonicKitTests.swift; sourceTree = "<group>"; };
0DDAF3A32408728600EA9427 /* PKC5.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PKC5.swift; sourceTree = "<group>"; };
12B9024EB02AB18E1F44789A /* Mnemonic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mnemonic.swift; sourceTree = "<group>"; };
1645FE576891F45DC72864F6 /* MnemonicKitTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = MnemonicKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
1D6F81AB601CF04F3F1E52E3 /* English.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = English.swift; sourceTree = "<group>"; };
@ -86,7 +87,7 @@
65B1627123A1131289B4110A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7DCB97C4881969FDB72C61DB /* MnemonicKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MnemonicKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BA1EBAC8ABDF9E72ABA1B642 /* CryptoSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CryptoSwift.framework; sourceTree = "<group>"; };
C3E5287598681E0527694214 /* vectors.json */ = {isa = PBXFileReference; path = vectors.json; sourceTree = "<group>"; };
C3E5287598681E0527694214 /* vectors.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = vectors.json; sourceTree = "<group>"; };
D2D9394FFD7755F40E53D60E /* Data+BitArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+BitArray.swift"; sourceTree = "<group>"; };
DC7EE929BD11BA8AB38F9C19 /* MnemonicKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MnemonicKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
EBA32888ED203FE1DA16BFF1 /* MnemonicKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MnemonicKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@ -114,7 +115,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
59FE4CF322226154B9B687CE /* CryptoSwift.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -122,7 +122,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
2C9FBE1A25B2CA86DB509726 /* CryptoSwift.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -162,6 +161,7 @@
12B9024EB02AB18E1F44789A /* Mnemonic.swift */,
256E6CB62D82160ACBA1512E /* String+MnemonicData.swift */,
07836B522CFA5AB2F61C4F9F /* Language */,
0DDAF3A32408728600EA9427 /* PKC5.swift */,
);
path = MnemonicKit;
sourceTree = "<group>";
@ -354,7 +354,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "swiftlint autocorrect --config .swiftlint.yml";
shellScript = "swiftlint autocorrect --config .swiftlint.yml\n";
};
E8B531151B3FAE302CDA4BEF /* SwiftLint */ = {
isa = PBXShellScriptBuildPhase;
@ -385,6 +385,7 @@
EFBEB3B343A9FDDD7B67FF88 /* Data+BitArray.swift in Sources */,
D4460C3982D7B9A90D99C790 /* English.swift in Sources */,
C3A836752BC9FC7C89A398C5 /* Mnemonic.swift in Sources */,
0DDAF3A52408728600EA9427 /* PKC5.swift in Sources */,
9374718ABBF77ACE41A92B18 /* String+MnemonicData.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -397,6 +398,7 @@
8EAFFDA8F2A30674EA9EBBBC /* Data+BitArray.swift in Sources */,
934F1409AF864AAA0AB52FDA /* English.swift in Sources */,
122777029525BA9CC4F9A958 /* Mnemonic.swift in Sources */,
0DDAF3A42408728600EA9427 /* PKC5.swift in Sources */,
81D18E658D26212E4D7647D8 /* String+MnemonicData.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -448,7 +450,7 @@
);
INFOPLIST_FILE = MnemonicKit/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -482,6 +484,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_BUNDLE_IDENTIFIER = "com.keefertaylor.MnemonicKit-macOS";
PRODUCT_NAME = MnemonicKit;
SDKROOT = macosx;
@ -510,6 +513,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_BUNDLE_IDENTIFIER = "com.keefertaylor.MnemonicKit-macOS";
PRODUCT_NAME = MnemonicKit;
SDKROOT = macosx;
@ -575,7 +579,7 @@
);
INFOPLIST_FILE = MnemonicKit/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -653,7 +657,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks $(PROJECT_DIR)/Carthage/Build/iOS";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_VERSION = 5.0;
@ -710,7 +719,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks $(PROJECT_DIR)/Carthage/Build/iOS";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -1,6 +1,4 @@
// Copyright Keefer Taylor, 2018
import CryptoSwift
import Foundation
public extension UInt8 {
@ -24,9 +22,18 @@ public extension UInt8 {
public extension Data {
func toBitArray() -> [String] {
var toReturn = [String]()
for num: UInt8 in bytes {
for num in [UInt8](self) {
toReturn.append(contentsOf: num.mnemonicBits())
}
return toReturn
}
}
public extension Array where Element == UInt8 {
func toBitArray() -> [String] {
var toReturn = [String]()
for num in self {
toReturn.append(contentsOf: num.mnemonicBits())
}
return toReturn
}
}

View File

@ -1,143 +1,164 @@
// Copyright Keefer Taylor, 2018
import CryptoSwift
import CryptoKit
import Foundation
import Security
public enum MnemonicLanguageType {
case english
case chinese
case english
case chinese
func words() -> [String] {
switch self {
case .english:
return String.englishMnemonics
case .chinese:
return String.chineseMnemonics
func words() -> [String] {
switch self {
case .english:
return String.englishMnemonics
case .chinese:
return String.chineseMnemonics
}
}
}
}
public enum Mnemonic {
/// Generate a mnemonic from the given hex string in the given language.
///
/// - Parameters:
/// - hexString: The hex string to generate a mnemonic from.
/// - language: The language to use. Default is english.
public static func mnemonicString(from hexString: String, language: MnemonicLanguageType = .english) -> String? {
let seedData = hexString.mnemonicData()
let hashData = seedData.sha256()
let checkSum = hashData.toBitArray()
var seedBits = seedData.toBitArray()
/// Generate a mnemonic from the given hex string in the given language.
///
/// - Parameters:
/// - hexString: The hex string to generate a mnemonic from.
/// - language: The language to use. Default is english.
public static func mnemonicString(from hexString: String, language: MnemonicLanguageType = .english) -> String? {
let seedData = hexString.mnemonicData()
let hashData = SHA256.hash(data: seedData)
let checkSum = hashData.bytes.toBitArray()
var seedBits = seedData.toBitArray()
for i in 0 ..< seedBits.count / 32 {
seedBits.append(checkSum[i])
}
let words = language.words()
let mnemonicCount = seedBits.count / 11
var mnemonic = [String]()
for i in 0 ..< mnemonicCount {
let length = 11
let startIndex = i * length
let subArray = seedBits[startIndex ..< startIndex + length]
let subString = subArray.joined(separator: "")
let index = Int(strtoul(subString, nil, 2))
mnemonic.append(words[index])
}
return mnemonic.joined(separator: " ")
}
/// Generate a deterministic seed string from the given inputs.
///
/// - Parameters:
/// - mnemonic: The mnemonic to use.
/// - iterations: The iterations to perform in the PBKDF2 algorithm. Default is 2048.
/// - passphrase: An optional passphrase. Default is the empty string.
/// - language: The language to use. Default is english.
public static func deterministicSeedString(
from mnemonic: String,
iterations: Int = 2_048,
passphrase: String = "",
language _: MnemonicLanguageType = .english
) -> String? {
guard self.validate(mnemonic: mnemonic),
let normalizedData = self.normalized(string: mnemonic),
let saltData = normalized(string: "mnemonic" + passphrase) else {
return nil
}
let passwordBytes = normalizedData.bytes
let saltBytes = saltData.bytes
do {
let bytes =
try PKCS5.PBKDF2(password: passwordBytes, salt: saltBytes, iterations: iterations, variant: .sha512).calculate()
return bytes.toHexString()
} catch {
return nil
}
}
/// Generate a mnemonic of the given strength and given language.
///
/// - Parameters:
/// - strength: The strength to use. This must be a multiple of 32.
/// - language: The language to use. Default is english.
public static func generateMnemonic(strength: Int, language: MnemonicLanguageType = .english)
-> String? {
guard strength % 32 == 0 else {
return nil
}
let count = strength / 8
let bytes = [UInt8](repeating: 0, count: count)
guard SecRandomCopyBytes(kSecRandomDefault, count, UnsafeMutablePointer<UInt8>(mutating: bytes)) != -1 else {
return nil
}
let data = Data(bytes)
let hexString = data.toHexString()
return mnemonicString(from: hexString, language: language)
}
/// Validate that the given string is a valid mnemonic.
public static func validate(mnemonic: String) -> Bool {
let normalizedMnemonic = mnemonic.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
let mnemonicComponents = normalizedMnemonic.components(separatedBy: " ")
guard !mnemonicComponents.isEmpty else {
return false
}
// Use the first component of the mnemonic to determine the language, then make sure all
// subsequent components are in that language.
if String.englishMnemonics.contains(mnemonicComponents[0]) {
for mnemonicComponent in mnemonicComponents {
guard String.englishMnemonics.contains(mnemonicComponent) else {
return false
for i in 0 ..< seedBits.count / 32 {
seedBits.append(checkSum[i])
}
}
return true
} else if String.chineseMnemonics.contains(mnemonicComponents[0]) {
for mnemonicComponent in mnemonicComponents {
guard String.chineseMnemonics.contains(mnemonicComponent) else {
return false
}
}
return true
} else {
return false
}
}
/// Change a string into data.
private static func normalized(string: String) -> Data? {
guard let data = string.data(using: .utf8, allowLossyConversion: true),
let dataString = String(data: data, encoding: .utf8),
let normalizedData = dataString.data(using: .utf8, allowLossyConversion: false) else {
return nil
let words = language.words()
let mnemonicCount = seedBits.count / 11
var mnemonic = [String]()
for i in 0 ..< mnemonicCount {
let length = 11
let startIndex = i * length
let subArray = seedBits[startIndex ..< startIndex + length]
let subString = subArray.joined(separator: "")
let index = Int(strtoul(subString, nil, 2))
mnemonic.append(words[index])
}
return mnemonic.joined(separator: " ")
}
/// Generate a deterministic seed string from the given inputs.
///
/// - Parameters:
/// - mnemonic: The mnemonic to use.
/// - iterations: The iterations to perform in the PBKDF2 algorithm. Default is 2048.
/// - passphrase: An optional passphrase. Default is the empty string.
/// - language: The language to use. Default is english.
public static func deterministicSeedString(
from mnemonic: String,
iterations: Int = 2_048,
passphrase: String = "",
language _: MnemonicLanguageType = .english
) -> String? {
guard self.validate(mnemonic: mnemonic),
let normalizedData = self.normalized(string: mnemonic),
let saltData = normalized(string: "mnemonic" + passphrase) else {
return nil
}
let passwordBytes = normalizedData.map { Int8(bitPattern: $0) }
do {
let bytes =
try PKCS5.PBKDF2SHA512(password: passwordBytes, salt: [UInt8](saltData), iterations: iterations)
return bytes.hexString
} catch {
return nil
}
}
/// Generate a mnemonic of the given strength and given language.
///
/// - Parameters:
/// - strength: The strength to use. This must be a multiple of 32.
/// - language: The language to use. Default is english.
public static func generateMnemonic(strength: Int, language: MnemonicLanguageType = .english)
-> String? {
guard strength % 32 == 0 else {
return nil
}
let count = strength / 8
var bytes = [UInt8](repeating: 0, count: count)
guard SecRandomCopyBytes(kSecRandomDefault, count, &bytes) == errSecSuccess else { return nil }
return mnemonicString(from: bytes.hexString, language: language)
}
/// Validate that the given string is a valid mnemonic.
public static func validate(mnemonic: String) -> Bool {
let normalizedMnemonic = mnemonic.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
let mnemonicComponents = normalizedMnemonic.components(separatedBy: " ")
guard !mnemonicComponents.isEmpty else {
return false
}
// Use the first component of the mnemonic to determine the language, then make sure all
// subsequent components are in that language.
if String.englishMnemonics.contains(mnemonicComponents[0]) {
for mnemonicComponent in mnemonicComponents {
guard String.englishMnemonics.contains(mnemonicComponent) else {
return false
}
}
return true
} else if String.chineseMnemonics.contains(mnemonicComponents[0]) {
for mnemonicComponent in mnemonicComponents {
guard String.chineseMnemonics.contains(mnemonicComponent) else {
return false
}
}
return true
} else {
return false
}
}
/// Change a string into data.
fileprivate static func normalized(string: String) -> Data? {
guard let data = string.data(using: .utf8, allowLossyConversion: true),
let dataString = String(data: data, encoding: .utf8),
let normalizedData = dataString.data(using: .utf8, allowLossyConversion: false) else {
return nil
}
return normalizedData
}
}
extension PKCS5 {
public static func PBKDF2SHA512(password: String, salt: String, iterations: Int = 2_048, keyLength: Int = 64) throws -> Array<UInt8> {
guard let saltData = Mnemonic.normalized(string: salt) else {
throw PKCS5.Error.invalidInput
}
return try PBKDF2SHA512(password: password.utf8.map({ Int8(bitPattern: $0) }), salt: [UInt8](saltData), iterations: iterations, keyLength: keyLength)
}
}
extension Digest {
var bytes: [UInt8] { Array(makeIterator()) }
var data: Data { Data(bytes) }
var hexString: String {
bytes.hexString
}
}
extension Array where Element == UInt8 {
var hexString: String {
self.map { String(format: "%02x", $0) }.joined()
}
return normalizedData
}
}

37
MnemonicKit/PKC5.swift Normal file
View File

@ -0,0 +1,37 @@
//
// PKCS5.swift
//
//
// Created by Liu Pengpeng on 2019/10/10.
//
import CommonCrypto
import CryptoKit
import Foundation
public struct PKCS5 {
public enum Error: Swift.Error {
case invalidInput
}
public static func PBKDF2SHA512(password: Array<Int8>, salt: Array<UInt8>, iterations: Int = 2_048, keyLength: Int = 64) throws -> Array<UInt8> {
var bytes = [UInt8](repeating: 0, count: keyLength)
try bytes.withUnsafeMutableBytes { (outputBytes: UnsafeMutableRawBufferPointer) in
let status = CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password,
password.count,
salt,
salt.count,
CCPBKDFAlgorithm(kCCPRFHmacAlgSHA512),
UInt32(iterations),
outputBytes.baseAddress?.assumingMemoryBound(to: UInt8.self),
keyLength
)
guard status == kCCSuccess else {
throw Error.invalidInput
}
}
return bytes
}
}