티스토리 뷰
니모닉이란?
http://wiki.hash.kr/index.php/%EB%8B%88%EB%AA%A8%EB%8B%89
니모닉 - 해시넷
니모닉(Mnemonic)이란 지갑을 복구하기 위한 12개의 단어이다. 개인 키가 너무 복잡한 단어들로 구성되어 있기 때문에, 이를 쉽게 입력할 수 있도록 갖춰진 형식이다. 니모닉의 어원은 그리스 신화
wiki.hash.kr
한줄로 요약하자면
'기억하기 어려운 개인키를 생성하기 위한 값을 기억하기 비교적 쉬운 일상적인 단어로 바꿔서 보관하자' 정도로 말 할 수 있을 것 같다.
위의 페이지에서 적혀있는것을 보면 니모닉을 만들기 위한 순서와 구조를 확인 할 수 있다.
구현 순서:
1. 암호학적으로 랜덤한 128~256 bits의 시퀀스 S를 만든다.
2. S의 SHA-256 해시값 중에서 앞(왼쪽)에서 S의 길이 / 32비트만큼을 체크섬으로 만든다.
3. 2번에서 만든 체크섬을 S의 끝에 추가한다.
4. 3번에서 만든 시퀀스와 체크섬의 연결을 11 bits 단위로 자른다.
5. 각 각의 11비트를 2048(2^11)개의 미리 정의된 단어로 치환한다.
6. 단어 시퀀스로부터 순서를 유지하면서 니모닉 코드를 생성한다.
구현순서 및 이미지 출처: http://wiki.hash.kr/index.php/%EB%8B%88%EB%AA%A8%EB%8B%89
1. 암호학적으로 랜덤한 128~256 bits의 시퀀스 S를 만든다.
func randomBytes(length: Int) -> Data? { // 1. 랜덤값 생성
for _ in 0...1024 {
var data = Data(repeating: 0, count: length)
let result = data.withUnsafeMutableBytes { (body: UnsafeMutableRawBufferPointer) -> Int32? in
if let bodyAddress = body.baseAddress, body.count > 0 {
let pointer = bodyAddress.assumingMemoryBound(to: UInt8.self)
return SecRandomCopyBytes(kSecRandomDefault, 32, pointer)
} else {
return nil
}
}
if let notNilResult = result, notNilResult == errSecSuccess {
return data
}
}
return nil
}
랜덤 변수를 만드는 메서드를 만들어주자. 주의할점은 128~256 비트 크기 내의 32비트 단위로 자른 값만 허용이 된다. (128,
160, 192, 224, 256)
2. S의 SHA-256 해시값 중에서 앞(왼쪽)에서 S의 길이 / 32비트만큼을 체크섬으로 만든다.
func genMnemonicsFromEntropy(entropy: Data) -> [String]? {
let checksum = entropy.sha256() // 랜덤한 값인 entropy를 sha256알고리즘을 이용해 해시해주고
let checksumBits = entropy.count*8/32
let checksumData = checksum[0 ..< (checksumBits + 7)/8 ] // 2. 가장 앞의 32비트를 체크썸으로 만들어준다.
....
}
3. 2번에서 만든 체크섬을 S의 끝에 추가한다.
func genMnemonicsFromEntropy(entropy: Data) -> [String]? {
let checksum = entropy.sha256()
let checksumBits = entropy.count*8/32
let checksumData = checksum[0 ..< (checksumBits + 7)/8 ]
var fullEntropy = Data()
fullEntropy.append(entropy) // S를 만들고
fullEntropy.append(checksumData) // 3. S의 끝에 checksum을 추가한다.
....
}
4. 3번에서 만든 시퀀스와 체크섬의 연결을 11 bits 단위로 자른다.
func genMnemonicsFromEntropy(entropy: Data) -> [String]? {
let checksum = entropy.sha256()
let checksumBits = entropy.count*8/32
let checksumData = checksum[0 ..< (checksumBits + 7)/8 ]
var fullEntropy = Data()
fullEntropy.append(entropy)
fullEntropy.append(checksumData)
var returnValue = [String]()
for i in 0 ..< fullEntropy.count*8/11 {
guard let bits = fullEntropy.bitsInRange(i*11, 11) else { return nil } // 4. 11비트 단위로 자르자.
...
}
return returnValue
}
5. 각 각의 11비트를 2048(2^11)개의 미리 정의된 단어로 치환한다.
func genMnemonicsFromEntropy(entropy: Data) -> [String]? {
let checksum = entropy.sha256()
let checksumBits = entropy.count*8/32
let checksumData = checksum[0 ..< (checksumBits + 7)/8 ]
var fullEntropy = Data()
fullEntropy.append(entropy)
fullEntropy.append(checksumData)
var returnValue = [String]()
for i in 0 ..< fullEntropy.count*8/11 {
guard let bits = fullEntropy.bitsInRange(i*11, 11) else { return nil }
let index = Int(bits)
guard Words.englishWords.count > index else { return nil }
let word = Words.englishWords[index] // 5. 각 각의 11비트를 2048(2^11)개의 미리 정의된 단어로 치환한다.
returnValue.append(word) // 결과적으로 반환해줄 니모닉 배열에 단어를 더해주자.
}
return returnValue
}
6. 단어 시퀀스로부터 순서를 유지하면서 니모닉 코드를 생성한다.
니모닉 완성 !
니모닉 -> 엔트로피 변환
역순으로 실행 해주면 된다.
for mnemonic in mnemonics {
guard let idx = Words.englishWords.firstIndex(of: mnemonic) else { return nil }
let idxAsInt = Words.englishWords.startIndex.distance(to: idx)
let stringForm = String(UInt16(idxAsInt), radix: 2).leftPadding(toLength: 11, withPad: "0")
bitString.append(stringForm)
}
니모닉을 2진수로 변환한 후
let checksumBits = bitString[(bitString.count - bitString.count/33) ..< bitString.count]
guard let entropy = entropyBits.interpretAsBinaryData() else {
return nil
}
let checksum = String(entropy.sha256().bitsInRange(0, checksumBits.count)!, radix: 2).leftPadding(toLength: checksumBits.count, withPad: "0")
if checksum != checksumBits {
return nil
}
checksum이 맞는지 확인한다.
원문 출력 성공
----
모든 소스 코드는
https://github.com/MyiOSPlayground/Mnemonic
GitHub - MyiOSPlayground/Mnemonic: Mnemonic
Mnemonic. Contribute to MyiOSPlayground/Mnemonic development by creating an account on GitHub.
github.com
이곳에서 확인하실 수 있습니다.
코드의 대부분은
https://github.com/skywinder/web3swift
GitHub - skywinder/web3swift: Elegant Web3js functionality in Swift. Native ABI parsing and smart contract interactions.
Elegant Web3js functionality in Swift. Native ABI parsing and smart contract interactions. - GitHub - skywinder/web3swift: Elegant Web3js functionality in Swift. Native ABI parsing and smart contra...
github.com
이곳을 참조하였습니다.
'프로그래밍 > iOS' 카테고리의 다른 글
[iOS] Secure한 TextField 만들어보기 (0) | 2022.09.20 |
---|---|
Delegate를 확장해보자 (0) | 2020.11.17 |
Widget Extension getTimeline 함수의 호출주기에 대해서 (0) | 2020.11.16 |
- Total
- Today
- Yesterday
- Protocol
- swift
- SwiftUI
- Swift 니모닉
- modulemap
- module map
- cicd
- iOS 니모닉
- ios
- iOS Mnemonic
- XCode Cloud
- isSecureTextEntry
- Tuist
- widget extension
- XCodeGen
- arc
- 순환참조
- 니모닉
- iOS wallet
- Gitlab Runner
- RxSwift
- firebase distribution
- Secure Enclave
- flatMap
- associated type
- Fastlane
- cd
- Objective-C
- Delegate
- CI
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |