Adding MnemonicKit sources to XCode.
This commit is contained in:
parent
b9aea2d689
commit
176d9ae9f8
|
@ -12,6 +12,10 @@
|
|||
778602B42186370E0036843F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 778602B22186370E0036843F /* Main.storyboard */; };
|
||||
778602B62186370F0036843F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 778602B52186370F0036843F /* Assets.xcassets */; };
|
||||
778602B92186370F0036843F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 778602B72186370F0036843F /* LaunchScreen.storyboard */; };
|
||||
778602C6218638FB0036843F /* String+MnemonicData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778602C2218638FB0036843F /* String+MnemonicData.swift */; };
|
||||
778602C7218638FB0036843F /* CKMnemonic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778602C3218638FB0036843F /* CKMnemonic.swift */; };
|
||||
778602C8218638FB0036843F /* Data+CKBitArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778602C4218638FB0036843F /* Data+CKBitArray.swift */; };
|
||||
778602C9218638FB0036843F /* Language in Resources */ = {isa = PBXBuildFile; fileRef = 778602C5218638FB0036843F /* Language */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
|
@ -22,6 +26,10 @@
|
|||
778602B52186370F0036843F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
778602B82186370F0036843F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
778602BA2186370F0036843F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
778602C2218638FB0036843F /* String+MnemonicData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+MnemonicData.swift"; sourceTree = "<group>"; };
|
||||
778602C3218638FB0036843F /* CKMnemonic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CKMnemonic.swift; sourceTree = "<group>"; };
|
||||
778602C4218638FB0036843F /* Data+CKBitArray.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Data+CKBitArray.swift"; sourceTree = "<group>"; };
|
||||
778602C5218638FB0036843F /* Language */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Language; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -54,6 +62,7 @@
|
|||
778602AD2186370E0036843F /* Sources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
778602C1218638BF0036843F /* MnemonicKit */,
|
||||
778602C0218637FB0036843F /* App */,
|
||||
);
|
||||
path = Sources;
|
||||
|
@ -72,6 +81,17 @@
|
|||
path = App;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
778602C1218638BF0036843F /* MnemonicKit */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
778602C3218638FB0036843F /* CKMnemonic.swift */,
|
||||
778602C4218638FB0036843F /* Data+CKBitArray.swift */,
|
||||
778602C5218638FB0036843F /* Language */,
|
||||
778602C2218638FB0036843F /* String+MnemonicData.swift */,
|
||||
);
|
||||
path = MnemonicKit;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
|
@ -130,6 +150,7 @@
|
|||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
778602C9218638FB0036843F /* Language in Resources */,
|
||||
778602B92186370F0036843F /* LaunchScreen.storyboard in Resources */,
|
||||
778602B62186370F0036843F /* Assets.xcassets in Resources */,
|
||||
778602B42186370E0036843F /* Main.storyboard in Resources */,
|
||||
|
@ -143,8 +164,11 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
778602C8218638FB0036843F /* Data+CKBitArray.swift in Sources */,
|
||||
778602B12186370E0036843F /* ViewController.swift in Sources */,
|
||||
778602AF2186370E0036843F /* AppDelegate.swift in Sources */,
|
||||
778602C6218638FB0036843F /* String+MnemonicData.swift in Sources */,
|
||||
778602C7218638FB0036843F /* CKMnemonic.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,122 @@
|
|||
//
|
||||
// CKMnemonic.swift
|
||||
// Pods
|
||||
//
|
||||
// Created by 仇弘扬 on 2017/7/24.
|
||||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CryptoSwift
|
||||
import Security
|
||||
|
||||
public enum CKMnemonicLanguageType {
|
||||
case english
|
||||
|
||||
case chinese
|
||||
|
||||
func words() -> [String] {
|
||||
switch self {
|
||||
case .english:
|
||||
return String.englishMnemonics
|
||||
case .chinese:
|
||||
return String.chineseMnemonics
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum CKMnemonicError: Error
|
||||
{
|
||||
case invalidStrength
|
||||
case unableToGetRandomData
|
||||
case unableToCreateSeedData
|
||||
}
|
||||
|
||||
public class CKMnemonic: NSObject {
|
||||
public static func mnemonicString(from hexString: String, language: CKMnemonicLanguageType) throws -> String {
|
||||
let seedData = hexString.ck_mnemonicData()
|
||||
// print("\(hexString.characters.count)\t\(seedData.count)")
|
||||
let hashData = seedData.sha256()
|
||||
// print(hashData.toHexString())
|
||||
let checkSum = hashData.ck_toBitArray()
|
||||
// print(checkSum)
|
||||
var seedBits = seedData.ck_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: "")
|
||||
// print(subString)
|
||||
|
||||
let index = Int(strtoul(subString, nil, 2))
|
||||
mnemonic.append(words[index])
|
||||
}
|
||||
return mnemonic.joined(separator: " ")
|
||||
}
|
||||
|
||||
public static func deterministicSeedString(from mnemonic: String, passphrase: String = "", language: CKMnemonicLanguageType) throws -> String {
|
||||
|
||||
func normalized(string: String) -> Data? {
|
||||
guard let data = string.data(using: .utf8, allowLossyConversion: true) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let dataString = String(data: data, encoding: .utf8) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let normalizedData = dataString.data(using: .utf8, allowLossyConversion: false) else {
|
||||
return nil
|
||||
}
|
||||
return normalizedData
|
||||
}
|
||||
|
||||
guard let normalizedData = normalized(string: mnemonic) else {
|
||||
return ""
|
||||
}
|
||||
|
||||
guard let saltData = normalized(string: "mnemonic" + passphrase) else {
|
||||
return ""
|
||||
}
|
||||
|
||||
let password = normalizedData.bytes
|
||||
let salt = saltData.bytes
|
||||
|
||||
do {
|
||||
let bytes = try PKCS5.PBKDF2(password: password, salt: salt, iterations: 2048, variant: .sha512).calculate()
|
||||
|
||||
return bytes.toHexString()
|
||||
} catch {
|
||||
// print(error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
public static func generateMnemonic(strength: Int, language: CKMnemonicLanguageType) throws -> String {
|
||||
guard strength % 32 == 0 else {
|
||||
throw CKMnemonicError.invalidStrength
|
||||
}
|
||||
|
||||
let count = strength / 8
|
||||
let bytes = Array<UInt8>(repeating: 0, count: count)
|
||||
let status = SecRandomCopyBytes(kSecRandomDefault, count, UnsafeMutablePointer<UInt8>(mutating: bytes))
|
||||
// print(status)
|
||||
if status != -1 {
|
||||
let data = Data(bytes: bytes)
|
||||
let hexString = data.toHexString()
|
||||
// print(hexString)
|
||||
|
||||
return try mnemonicString(from: hexString, language: language)
|
||||
}
|
||||
throw CKMnemonicError.unableToGetRandomData
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Data+CKBitArray.swift
|
||||
// CKMnemonic
|
||||
//
|
||||
// Created by 仇弘扬 on 2017/7/25.
|
||||
// Copyright © 2017年 askcoin. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CryptoSwift
|
||||
|
||||
public extension UInt8 {
|
||||
public func ck_bits() -> [String] {
|
||||
let totalBitsCount = MemoryLayout<UInt8>.size * 8
|
||||
|
||||
var bitsArray = [String](repeating: "0", count: totalBitsCount)
|
||||
|
||||
for j in 0 ..< totalBitsCount {
|
||||
let bitVal: UInt8 = 1 << UInt8(totalBitsCount - 1 - j)
|
||||
let check = self & bitVal
|
||||
|
||||
if (check != 0) {
|
||||
bitsArray[j] = "1"
|
||||
}
|
||||
}
|
||||
return bitsArray
|
||||
}
|
||||
}
|
||||
|
||||
public extension Data {
|
||||
public func ck_toBitArray() -> [String] {
|
||||
var toReturn = [String]()
|
||||
for num: UInt8 in bytes {
|
||||
|
||||
toReturn.append(contentsOf: num.ck_bits())
|
||||
}
|
||||
return toReturn
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// String+MnemonicData.swift
|
||||
// CKMnemonic
|
||||
//
|
||||
// Created by 仇弘扬 on 2017/7/25.
|
||||
// Copyright © 2017年 askcoin. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension String
|
||||
{
|
||||
public func ck_mnemonicData() -> Data {
|
||||
let length = characters.count
|
||||
let dataLength = length / 2
|
||||
var dataToReturn = Data(capacity: dataLength)
|
||||
|
||||
var index = 0
|
||||
var chars = ""
|
||||
for char in characters {
|
||||
chars += String(char)
|
||||
if index % 2 == 1 {
|
||||
let i: UInt8 = UInt8(strtoul(chars, nil, 16))
|
||||
dataToReturn.append(i)
|
||||
chars = ""
|
||||
}
|
||||
index += 1
|
||||
}
|
||||
|
||||
return dataToReturn
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue