してみるテストロゴ
Apache 2.4系でHTTP/2サーバを構築してみるテスト。

Multi-prime RSAを使ってみた

これまで、OpenSSLのRSA暗号では、2個の素数を使ってきました。

しかし、別に素数の個数を2個に限定する必要はありません。

詳細はコチラのサイトが詳しいので、割愛いたしますが、RSA暗号の原理からは、3個以上の素数でも実現できます。

OpenSSL 1.1.1になって、3個以上の素数を使う秘密鍵、すなわちMulti-prime RSAに対応したので、早速使ってみました。

後述しますが、素数の桁数が減るため、従来のRSAよりは因数分解しやすくなります。つまり、暗号強度が若干下がると考えらえます。

十分に理解してからご利用いただければ幸いです。

秘密鍵を作ってみる。

3個以上の素数を利用するには、以下のオプションをつけて秘密鍵を作成します。

/usr/local/bin/openssl にOpenSSL 1.1.1のバイナリがインストールされている前提です。

まず、乱数を適当に発生させて、その後RSA秘密鍵を生成します。

以下のコマンド例では秘密鍵DESやAESで暗号化していないので、取り扱には注意してください。

$ /usr/local/bin/openssl md5 * > /tmp/rand.dat.
$ /usr/local/bin/openssl genrsa -rand /tmp/rand.dat -primes 3 > prime3.key
Generating RSA private key, 2048 bit long modulus (3 primes)
..........................................................++++
.......................................++++
.....................++++
e is 65537 (0x010001)

勘の良い方は、お気づきだと思いますが、いつもは2行分しか出てこない、ピリオドと+の行が3つあります。

つまり、3つの素数を生成していることが判ります。

生成された秘密鍵に素数が3つ含まれていることは、以下のコマンドでわかります。

$ /usr/local/bin/openssl rsa -in prime3.key -text
RSA Private-Key: (2048 bit, 3 primes)
modulus:
(…省略…)
publicExponent: 65537 (0x10001)
privateExponent:
(…省略…)
prime1:
(…省略…)
prime2:
(…省略…)
exponent1:
(…省略…)
exponent2:
(…省略…)
coefficient:
(…省略…)
prime3:
(…省略…)
exponent3:
(…省略…)
coefficient3: (…省略…)

writing RSA key -----BEGIN RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----

ここで従来のopenssl genrsaコマンドの秘密鍵と比較してほしいのですが、従来のprime1,prime2はそれぞれ、1024ビット前後の桁数の値が入っていました。

それに対して、今回生成した秘密鍵のprime 1,prime 2, prime 3は、それぞれ、682ビット前後の桁数の値が入っています。

つまり、2048ビットの1/3の約682ビットの素数が3つで、2048ビットになっています。

一つ当たりの素数の桁が小さくなると、署名の際に利用する、「中国の剰余定理」の計算が楽になります。

つまり秘密鍵の素数の桁数(ビット数)が減ると、それに応じて、演算負荷が減りますので、処理速度は上がる可能性があります。

 

一方、前述の通り、素数のビット数が減っているため、総当たりの因数分解がしやすくなっています。

つまり、従来のRSA暗号よりは暗号強度が弱くなっていると考えられます。

そのため、multi-prime RSAは、暗号強度について一定の評価が定まるまでは、積極的に使うことはお勧めしません。

 

私見ですが、multi-prime RSAについては、素数の桁数を基準にセキュリティービットを定め、公開鍵の長さを量子耐性として扱う新しい基準があるといいような気がします。

使うにしても、素数の個数は、3より大きくしない方がよさそうです。

multi-prime RSAのサーバ証明書を取得してみる。

次に、multi-prime RSAの秘密鍵にサーバ証明書を発行できるか、試してみます。

今回は、取得できることだけを説明するので、やりかたは概要だけ説明します。

まず、カスタムの秘密鍵なので、自前でCSRを用意します。

Let's Encryptの場合、カスタムのCSRを使う場合は、DER形式のCSRを使うことが多いので、der形式のオプションを例示します。

# /usr/local/bin/openssl req -new -key prime3.key -subj="/CN=example.com" -out prime3.der -outform der
# /usr/local/bin/openssl req -in prime3.der -inform der -text	
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: CN = example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:b7:83:2d:2b:02:1a:e9:47:af:54:88:b6:69:45:
(…省略…)
                    95:99
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha256WithRSAEncryption
         94:c2:7f:6f:53:a4:4d:37:e8:63:fa:eb:ba:65:23:4c:1f:7f:
(…省略…)
         52:85:67:8b
-----BEGIN CERTIFICATE REQUEST-----
(…省略…)
-----END CERTIFICATE REQUEST-----

実は、このCSRからは、サーバの秘密鍵が、multi-prime RSAかどうかは、わかりません。

Modulusを因数分解しないと、multi-prime RSAだとわからないのです。

なので、認証局から見ても、従来のRSAのCSRと、差がないので、特別に対応する必要はありません。

そのまま従来通り行えば、multi-prime RSAの秘密鍵の証明書が得られます。

以下を参考に、Let's Encryptから証明書を取得してください。

あとは、いつも通り、Webサーバに設定を入れて再起動すればmulti-prime RSAのサーバ証明書でWebサーバが稼働します。

Chrome, Firefox, Microsoft Edgeで試してみましたが、普通に接続できます。

multi-prime RSAのベンチマーク

multi-prime RSAのベンチマークを、以下のコマンドでとってみました。

$ /usr/local/bin/openssl speed -primes 3 rsa2048 rsa3072
enerate multi-prime RSA key for rsa2048
Doing 2048 bits private rsa's for 10s: 10774 2048 bits private RSA's in 9.89s
Doing 2048 bits public rsa's for 10s: 280852 2048 bits public RSA's in 9.88s
Generate multi-prime RSA key for rsa3072
Doing 3072 bits private rsa's for 10s: 7753 3072 bits private RSA's in 9.88s
Doing 3072 bits public rsa's for 10s: 135875 3072 bits public RSA's in 9.91s
OpenSSL 1.1.1-pre8 (beta) 20 Jun 2018
built on: Wed Jun 27 11:41:01 2018 UTC
options:bn(64,64) rc4(16x,int) des(int) aes(partial) idea(int) blowfish(ptr)
compiler: cc -fPIC -pthread -Wa,--noexecstack -Qunused-arguments -Wall -O3 -enable-tls1_3 -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPADLOCK_ASM -DPOLY1305_ASM -D_THREAD_SAFE -D_REENTRANT -DNDEBUG
                  sign    verify    sign/s verify/s
rsa 2048 bits 0.000918s 0.000035s   1089.3  28418.2
rsa 3072 bits 0.001275s 0.000073s    784.5  13705.3	

同様に、-primes 2の場合と、併せて、以下の表の

素数の数 鍵長 署名 検証
処理時間 毎秒 処理時間 毎秒
-primes 2 2048 0.817[ms] 1223.3 0.036[ms] 28134.4
3072 3.759[ms] 266.0 0.074[ms] 13593.1
-primes 3 2048 0.918[ms] 1089.3 0.035[ms] 28418.2
3072 1.275[ms] 784.5 0.073[ms] 13705.3

となりました。

 

まず、検証にかかる時間に、秘密鍵の素数の個数による差はありませんでした。

これは、CSRや証明書自体が、従来のRSAと変わらないこと、特に、Exponent: 65537 (0x10001)であることからも、予想通りといえます。

 

問題は、署名にかかる時間です。

2048bitでは、primes 2の方が速いので変だなとおもったら、案の定、

https://github.com/openssl/openssl/issues/6808

とチケットが上がっていました。

パフォーマンスが安定するまで、もう少しかかりそうですね。

NEXT >> トップページに戻る

©Copyrights 2015-2018, non-standard programmer

このサイトは、あくまでも私の個人的体験を、綴ったものです。 軽く参考程度にご利用ください。