Goのcrypto/rsaのEncryptPKCS1v15の使い方メモ

ちょっと自信がないので、OpenSSLでやったのと同じ結果になるか確かめてみる。

とりあえずこの記事を見ながらやってみる。

d.hatena.ne.jp

鍵の生成

まずは鍵の生成。デフォルトだと2048bitだけど、RStudioが使っている鍵と合わせたいのであえて1024bitの鍵を生成する。public exponentはF4(0x10001)にする。これはデフォルトのままで大丈夫だけどいちおう明示的に指定している。

$ openssl genrsa -f4 1024 > test.key
Generating RSA private key, 1024 bit long modulus
...............................................++++++
..................++++++
e is 65537 (0x10001)

modulus

この鍵のmodulusを確かめる。modulusを確かめるにはopenssl rsa -modulusで確かめられる。

$ openssl rsa -modulus -noout < test.key
Modulus=C39863E719AD6022C444BE38FB6F396795CBA307534CFB3B0DB674F0741BEB498C543F5D3706716C99AF11282D45EF105784FEBC19D9095737376612978C8B1C01391ADE12CD7D0F4D6D64B558BDB9A6792AD2902C0EDE9B0649282B1B8A04DF930825AB4B95B2EF261594F7EE3CFDA6C39C42E044317E7E072220017FFF160B

暗号化

適当なテキストを暗号化する。openssl rsautl -encryptというコマンドがあるらしい。知らんかった。

$ echo test | openssl rsautl -encrypt -pkcs -inkey test.key
u↑S�T����◄↔��E��§?8♦�↔¶ۧת�☼�?��,♣�p�s?&�Y~�����♦H↨�/��S��c�.�o�y�Le�ӎ�!4N����{Na§RϼN�%3���☺�w����h�6↕■�o���qb%m��R�a

なにやら文字化けした。これはバイト列なのでBASE64化しといたほうがいいらしい。openssl base64 -eを使う。乱数があるので毎回結果は違う。

$ echo -n "test" | openssl rsautl -encrypt -pkcs -inkey test.key | openssl base64 -e
naqVeUXTPwgL7I3+Fhcg2SUzPjvIsbD4ZEywxxBc8hhlUSsKpufyurxVlP0PHxbr
9xKMH5Ry/Y+wB3FWGTEsUMDYOXyV53CDUa9ohNrcZVHpXP+fzBRLXdFkqvBCwFP8
SkLrCMp6m32bY9KpHn1GJ60tqCQeo2EozqAj5PrpG/M=

OpenSSLで復号

今度はさっきと逆に、BASE64をでコードして、同じ鍵でdecryptしてやればいい。Goで暗号化した文字列も同じ方法で復号できるはず。

$ echo 'UAgUOzol/YCryxdocFkLJ5FtaPlrJ3TJXU9SwjIeYBaqEfutCphJU+vllkY3kNIWJn0wqI5HTZAyYmhjDO+/yniNDO+gRbhDAHcRYlSpCMeS6VgAV3meDUNfwl0UxPiB0JqTsR9aXxUoLPKLc+ESlbNPAZ0jVQ97vqTS1czICyM=' \
> | openssl base64 -d | openssl rsautl -decrypt -pkcs -inkey test.key
test

Go

いよいよGoでやってみる。

まず、modulusをbig.Intに変換する。math/bigにはParseFloat()Parse()があるけどどっちもFloatしか返さなくてどうするの??と混乱してたけど、まずnewしてからsetString()するらしい。

big - The Go Programming Language

modulusString := "C39863E719AD6022C444BE38FB6F396795CBA307534CFB3B0DB674F0741BEB498C543F5D3706716C99AF11282D45EF105784FEBC19D9095737376612978C8B1C01391ADE12CD7D0F4D6D64B558BDB9A6792AD2902C0EDE9B0649282B1B8A04DF930825AB4B95B2EF261594F7EE3CFDA6C39C42E044317E7E072220017FFF160B"

modulusInt := new(big.Int)
modulusInt.SetString(modulusInt, 16)

このmodulusを使ってrsa.PublicKeyをつくる。Nがmodulus、Eがpublic exponent。

rsa - The Go Programming Language

pubkey := &rsa.PublicKey{N: modulusInt, E: 0x10001}

rsa.EncryptPKCS1v15()は、他に乱数生成器として?io.Readerを引数に取る。rand.Readerとかを指定しておくのがお作法らしい。

https://golang.org/pkg/crypto/rsa/#EncryptPKCS1v15

result, _ := rsa.EncryptPKCS1v15(rand.Reader, pubkey, []byte("test"))

で、これをBASE64エンコードする。

base64 - The Go Programming Language

encoded := base64.StdEncoding.EncodeToString(result)

https://play.golang.org/p/C4Ersc5Gub

OpenSSLで復号

やってみる。

$ echo 'm0ofaVSC8djEIUCU/OwDmz1fnSlnhzHMUWCrx5jkNDrlG7ixD20/1tqGHRGhoCJ1jQCrg3ZHkD3bnWOKHeBlGld9In8WObdpJFrBQXIm8vVh+GqOlzHxumt45K3n68cJ6uZpZwsxuoOL5+an4yIPjgBENqmcW4amfyrOo/+3ICw=' \
> | openssl base64 -d | openssl rsautl -decrypt -pkcs -inkey test.key
test

ということであってそう。