BLOG

将来の夢はおもしろお兄さんです。

SSH 公開鍵ユーティリティを Go と Python で作った

はじめに

こんにちは、 NHK 技研公開に行った所、何度も「学生さんですか?」と訊かれた yosida95 です。

タイトルのとおり、 Pure Go と Pure Python で SSH 公開鍵ユーティリティを作ったのでご案内します。

Go
yosida95/golang-sshkey
Python
yosida95/python-sshkey

SSH 公開鍵ユーティリティ

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMjH3YZMNFG8cnl98t6w6Ca152cnTsWyrZ56WYSYNkEax1grChZB3P4NcxmtqFxrN2wMXuATiqp62cNkj8wAQUIwRgUnqKkkaQTDyLEDVaTZ75RsZIE4vM/YJ5AzmbCIHK8u6YvfM8fIlv4PKzbMHIIcZvuG9ZYQ+ZEKmSIVxIKZNVfUYyoRK6RFPEMjZPGGoOFRBo8sifsJDLDIBLWOgR4Nf2rWuV+ZuySXX9wjsv42iIdp9RVJcjQXHmi7AKVifKfFJwM+6aPiQcAaWnINzvUnqQK5yrWEp5tVH49bFL92UNriT+LTozloILCj5SdqXQ+JbKp/6EobY96bWhkwyZ yosida95@yosida95

上に示したのが SSH 公開鍵で、ちなみに普段ぼくが使っているものです。 よく見るフォーマットだと思います。

この公開鍵は、目に見える通り3つのパートから成っていて、左からアルゴリズム、公開鍵、コメントとなっています。 また、2つめの公開鍵のパートは BASE64 エンコードされていて、デコードすると RSA の場合は “ssh-rsa”, exponent (E), modulus (N) のように、アルゴリズムと公開鍵のパラメーターが含まれています。

今回作ったユーティリティでは、 Printable ASCII で表現される公開鍵をデコードし、コメントや鍵長を取得したり、フィンガープリント(鍵指紋)を計算したり、 golang-sshkey の場合は crypto/rsa の *rsa.PublicKey のような標準的な構造体に変換したりできます。

インストール

golang-sshkey

$ go get github.com/yosida95/golang-sshkey

python-sshkey

$ pip install sshkey

使い方

golang-sshkey

example_sshkey.go
     package main

     import (
             "crypto"
             "crypto/rsa"
             "fmt"

             "github.com/yosida95/golang-sshkey"
     )

     const (
             marshaledPub = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMjH3YZMNFG8cnl98t6w6Ca152cnTsWyrZ56WYSYNkEax1grChZB3P4NcxmtqFxrN2wMXuATiqp62cNkj8wAQUIwRgUnqKkkaQTDyLEDVaTZ75RsZIE4vM/YJ5AzmbCIHK8u6YvfM8fIlv4PKzbMHIIcZvuG9ZYQ+ZEKmSIVxIKZNVfUYyoRK6RFPEMjZPGGoOFRBo8sifsJDLDIBLWOgR4Nf2rWuV+ZuySXX9wjsv42iIdp9RVJcjQXHmi7AKVifKfFJwM+6aPiQcAaWnINzvUnqQK5yrWEp5tVH49bFL92UNriT+LTozloILCj5SdqXQ+JbKp/6EobY96bWhkwyZ [email protected]"
     )

     func main() {
             pubkey, err := sshkey.UnmarshalPublicKey(marshaledPub)
             if err != nil {
                     panic(err)
             }
             nativePub := pubkey.Public().(*rsa.PublicKey)

             fmt.Println(pubkey.Type() == sshkey.KEY_RSA)
             fmt.Println(nativePub.E)
             fmt.Println(pubkey.Length())
             fmt.Println(pubkey.Comment())

             fp, _ := sshkey.PrettyFingerprint(pubkey, crypto.MD5)
             fmt.Println(fp)

             // Output:
             // true
             // 65537
             // 2048
             // [email protected]
             // 17:59:d1:53:0a:38:33:91:ff:8c:f8:f6:16:89:ed:f0
     }

python-sshkey

example_sshkey.py
 # -*- coding: utf-8 -*-

 import sshkey.public

 marshaled_pub = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMjH3YZMNFG8cnl98t6w6Ca152cnTsWyrZ56WYSYNkEax1grChZB3P4NcxmtqFxrN2wMXuATiqp62cNkj8wAQUIwRgUnqKkkaQTDyLEDVaTZ75RsZIE4vM/YJ5AzmbCIHK8u6YvfM8fIlv4PKzbMHIIcZvuG9ZYQ+ZEKmSIVxIKZNVfUYyoRK6RFPEMjZPGGoOFRBo8sifsJDLDIBLWOgR4Nf2rWuV+ZuySXX9wjsv42iIdp9RVJcjQXHmi7AKVifKfFJwM+6aPiQcAaWnINzvUnqQK5yrWEp5tVH49bFL92UNriT+LTozloILCj5SdqXQ+JbKp/6EobY96bWhkwyZ [email protected]'


 def main():
     pub = sshkey.public.from_openssh(marshaled_pub)
     print(pub.type)  # => sshkey.public.SSHKeyType.RSA
     print(pub.length)  # => 2048
     print(pub.comment)  # => [email protected]
     print(pub.pretty_finger_print())  # => 17:59:d1:53:0a:38:33:91:ff:8c:f8:f6:16:89:ed:f0


 if __name__ == '__main__':
     main()

実績

実は今回作ったのは golang-sshkey の方だけで、 python-sshkey の方は半年前に作って公開していたものです。 この python-sshkey にはすでに、私が所属するゲヒルンが提供する Gehirn Infrastructure ServicesRS2 Plus で使われているという実績があります。

Gehirn RS2 Plus 公開鍵の管理 [シリーズGWS]第4回 Gehirn RS2 Plus のアカウントを作り SSH でログインする

また、近々 golang-sshkey の方も同様に Gehirn RS2 Plus で利用する予定があります。

おわりに

どちらのパッケージも3条項 BSD ライセンスで公開しています。 ご活用ください。 また、コントリビュートをお待ちしています。

こちらからは以上です。