モバイル版Gethにはキーストアファイル(UTC/JSON)をエクスポートするメソッドが用意されているが、プライベートキー(秘密鍵)を取得するメソッドは用意されていないので、定番であるkeythereum.jsをローカルのhtml経由で読み込みWKWebViewのインスタンスメソッドであるevaluateJavaScript()にてプライベートキーを取得するアプリを作ってみました。
ちなみにJavaScriptCoreにての稼働も試みましたが戻り値がUndefinedとなってしまいます。おそらくプリミティブな型しかサポートしていないのでしょう。
完成イメージ
Extract Private Keyボタンを押すと、UTC/JSONとpasswordをインプットにプライベートキーのデコードを試みます。成功した場合は画面下部にプライベートキーのバイト列が、失敗時はエラーメッセージを表示します。
手順
1. keythereum.min.jsをダウンロード
まずはgithubからkeythereum.min.jsをいただきます。distフォルダの中にあります。
2. keythereum.htmlを作成
プライベートキーを取得するjsコード
var privateKey = keythereum.recover(password, keyObject)
今回のキモはこのコードをSwiftから実行できるようにすることです。
Node.jsなしでも動くブラウザベース版を利用します。
<script src="keythereum.min.js" type="text/javascript"></script>
keythereum.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script src="keythereum.min.js" type="text/javascript"></script>
<script>
function privateKey(keyStoreJsonStr,password) {
var keyObject = JSON.parse(keyStoreJsonStr);
return keythereum.recover(password, keyObject).toString('hex');
}
</script>
</head>
</html>
keythereum.recover()のパラメタkeyObjectはJSONオブジェクトであるためストリングで渡せるようにラップしたpraivateKey()をhtmlに記述します。
3. プロジェクト作成/jsとhtmlを登録
シングルビューアプリケーションをテンプレートにプロジェクトを作成します。
keythereum.min.jsとkeythereum.htmlをプロジェクトにドラッグ・アンド・ドロップするか、Build Phase->Copy Bundle Resourcesから登録します。
4. UI作成
ストーリーボードにてUIを作成します。
ViewController.swift内のアウトレット変数と紐付けるオブジェクトを赤矢印で示しました。
5. ViewControllerの実装
ViewController.swift
import UIKit
import WebKit
class ViewController: UIViewController {
@IBOutlet weak var keyStoreText:UITextView!
@IBOutlet weak var passwordField:UITextField!
@IBOutlet weak var secretKeyLabel:UILabel!
// ダミーのWebview. JS実行用
//var webView = UIWebView()
var webView = WKWebView()
// テキストフィールド外をタップするとキーボードを隠す
@IBAction func hiddenKeyboard(_ sender: UITapGestureRecognizer) {
self.view.endEditing(true)
}
@IBAction func extractPrivateKey(_ sender:UIButton) {
// javascript:privateKey()のパラメタ
var param1:String = ""
let param2 = passwordField.text!
// keyStoreTextの複数行を1行にする
keyStoreText.text?.enumerateLines { (line, stop) -> () in
param1 += line.trimmingCharacters(in:.whitespacesAndNewlines)
}
// js評価文字列作成
let jsEvalStr = "privateKey('" + param1 + "','" + param2 + "');"
//let privateKey = webView.stringByEvaluatingJavaScript(from:jsEvalStr)
webView.evaluateJavaScript(jsEvalStr, completionHandler: {(res,error) in
guard let pk = res else {
self.secretKeyLabel.text = "fail to decode private key"
return
}
self.secretKeyLabel.text = pk as? String
})
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// ローカルのkeythereum.htmlをロード
// let html = Bundle.main.path(forResource: "keythereum", ofType: "html")
// webView.loadRequest(URLRequest(url: URL(string: html!)!))
let url = Bundle.main.url(forResource: "keythereum", withExtension: ".html")!
let urlRequest = URLRequest(url: url)
webView.load(urlRequest)
// パスワードフィールドを伏せ字モードに
passwordField.isSecureTextEntry = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
// Xcode 9.1 Swift4.0
UIWebViewのインスタンスメソッドであるstringByEvaluatingJavaScript()をコールするためにサイズ未指定でウェブビューをインスタンスしています。
//var webView = UIWebView()
var webView = WKWebView()
テキストビューの内容を改行とホワイトスペースを除きながら1行にしています。
keyStoreText.text?.enumerateLines { (line, stop) -> () in
param1 += line.trimmingCharacters(in:.whitespacesAndNewlines)
}
javascript実行コード文字列を編集しています。
let jsEvalStr = "privateKey('" + param1 + "','" + param2 + "');"
6. 稼働確認
抽出されたプライベートキーが正しいかどうかはEthTools.comで確認するのが便利です。
UTC/JSONをペースト、パスワードを入れて、Load Walletをクリック
Advanced(+)をクリックするとPrivate keyを見ることが出来ます
githubに置いときます
KeythereumSwift
Caution!! |
---|
紹介しておいてなんですが、プライベートキーはとても大切な情報です。本運用しているアカウントのプライベートキーをむやみにウェブで入力したりすることはおすすめできません。 |
2017.12.13改修
UIWebViewでなくWKWebViewを使用するように改修しました