Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

モバイル版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を使用するように改修しました

fromage-blanc
楽曲制作(ベリバービリバー/石川ひとみ等)と開発(Webシステム、iPhoneアプリ)を生業にしてます。
https://fromage-blanc-recette.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした