2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

BlockChainAdvent Calendar 2017

Day 5

【Swift4.0】keythereum.jsをSwiftから使う【Ethereum】

Last updated at Posted at 2017-12-08

モバイル版Gethにはキーストアファイル(UTC/JSON)をエクスポートするメソッドが用意されているが、プライベートキー(秘密鍵)を取得するメソッドは用意されていないので、定番であるkeythereum.jsをローカルのhtml経由で読み込みWKWebViewのインスタンスメソッドであるevaluateJavaScript()にてプライベートキーを取得するアプリを作ってみました。
ちなみにJavaScriptCoreにての稼働も試みましたが戻り値がUndefinedとなってしまいます。おそらくプリミティブな型しかサポートしていないのでしょう。

完成イメージ

key1.png

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から登録します。
key11.png

4. UI作成

ストーリーボードにてUIを作成します。
ViewController.swift内のアウトレット変数と紐付けるオブジェクトを赤矢印で示しました。
key12.png

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で確認するのが便利です。

Keyfileをクリック
key5.png

UTC/JSONをペースト、パスワードを入れて、Load Walletをクリック
key7.png

Advanced(+)をクリックするとPrivate keyを見ることが出来ます
key8.png

合ってます\(^o^)/
key10.png

githubに置いときます
KeythereumSwift

Caution!!
紹介しておいてなんですが、プライベートキーはとても大切な情報です。本運用しているアカウントのプライベートキーをむやみにウェブで入力したりすることはおすすめできません。

2017.12.13改修

UIWebViewでなくWKWebViewを使用するように改修しました

2
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?