RSA 2048 geração de keypair: via openssl 0.5s via gpg 30s, por que a diferença?

8

Geração de par de chaves RSA 2048: via openssl 0.5s via gpg 30s, por que a diferença Existem vários programas que podem gerar pares de chaves públicas / privadas RSA

GnuPG / OpenPGP, por exemplo, tem um wizzard sendo enviado via

gpg --gen-key

O OpenSSL pode gerar um par de chaves usando essas linhas de comando

openssl genrsa -out testkey.private 2048
openssl rsa -in testkey.private -pubout -out testkey.public

para a mesma coisa, que está gerando um par de chaves RSA 2048 bit Eu posso perceber - na mesma máquina - momentos bem diferentes.

openssl gera um par de chaves em cerca de 0,5s
gpg demora cerca de 30 e até anúncios "move o mouse para gerar aleatoriedade / entropia"

A diferença pode ser explicada? Eu sei que o gpg faz um pouco mais do que apenas a criação da chave RSA, mas eu escolho especificamente a opção (4)

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection?
Portanto, a única coisa gerada é um par de chaves RSA de 2048 bits. No entanto, a diferença de tempo é de 30 segundos?

Para mim, parece que ou o gpg está desperdiçando tempo desnecessariamente ou o OpenSSL não está esperando tempo suficiente e, portanto, cria chaves inseguras.

Minha pergunta é o que poderia explicar a diferença?

Atualizar

A criação de RSA deve tomar como entrada alguma aleatoriedade. Portanto, para ter certeza de que o speedy openssl não é simplesmente o resultado de usar alguma aleatoriedade armazenada, eu o rotulo várias vezes

time bash -c "for i in {1..50}; do  openssl genrsa -out /dev/null 2048 ;  done;"

que produz

real    0m16.577s
user    0m16.309s
sys 0m0.092s

que é que para 50 2048bits chaves RSA (suponho que preciso de muita entropia / aleatoriedade) openssl ainda só precisava de 16 segundos. Minha suposição aqui seria, portanto, a "resposta" que deve ser quebrada. Afinal, eu desconfio que meu Linux (um kernel 3.2.0-59) tenha se tornado tão bom em gerar aleatoriedade.

Talvez a diferença seja simplesmente que openssl usa /dev/urandom e gpg usa /dev/random , o que, se for verdade, poderia explicar a diferença de tempo, meu problema é que eu não sei como descobriria isso, para verificar isso.

update2

Para testar a fonte do random de openssl usei

strace -xe trace=file,read,write,close openssl genrsa -out testkey5.private 2048 2>&1 | grep random -A1

que produz

open("/dev/urandom", O_RDONLY|O_NOCTTY|O_NONBLOCK) = 4
read(4, "\x21\xd8\xaa\xf1\x2b\x5f\x4a\x89\x5d\x6c\x58\x82\xc1\x88\x21\x04\xfa\x5b\x18\x98\x8a\x34\x2b\xe3\xf3\xc0\xb1\xef\xfb\x44\x15\x09", 32) = 32

então parece que 32 bytes de /dev/urandom (não o "melhor" /dev/random ) é suficiente para o par de chaves RSA de 2048 bits no openssl. Portanto, é tão rápido!

Medidas

2048bit Geração de par de chaves RSA significa

  • 32 bytes de apenas /dev/urandom (usando openssl)
  • 300 bytes de dev/random (usando o openPGP GNU Privacy Guard)

isso explica, claro, a diferença de tempo!

    
por humanityANDpeace 16.03.2014 / 16:01

2 respostas

8

O GnuPG consome vários bytes de /dev/random para cada byte aleatório que realmente usa. Você pode facilmente verificar isso com este comando:

start cmd:> strace -e trace=open,read gpg --armor --gen-random 2 16 2>&1 | tail
open("/etc/gcrypt/rngseed", O_RDONLY)   = -1 ENOENT (No such file or directory)
open("/dev/urandom", O_RDONLY)          = 3
read(3, "\4Fp4j50F96V08", 16) = 16
open("/dev/random", O_RDONLY)           = 4
read(4, "/127...2653I"..., 300) = 128
read(4, "561+1...302@2"..., 172) = 128
read(4, "[2l?\...6iY3z"..., 44) = 44
open("/home/hl/.gnupg/random_seed", O_WRONLY|O_CREAT, 0600) = 5
cCVg2XuvdjzYiV0RE1uzGQ==
+++ exited with 0 +++

Para produzir 16 bytes de entropia de alta qualidade, o GnuPG lê 300 bytes de /dev/random .

Isso é explicado aqui: Arquitetura do Subsistema de Números Aleatórios

O Linux armazena no máximo 4096 bytes (veja cat /proc/sys/kernel/random/poolsize ) de entropia. Se um processo precisar de mais do que o disponível (veja cat /proc/sys/kernel/random/entropy_avail ), então o uso da CPU se torna mais ou menos irrelevante, já que a velocidade de alimentação do pool de entropia do kernel torna-se o fator relevante.

    
por 16.03.2014 / 16:42
6

Sua sugestão de que essa diferença ocorre porque openssl usa / dev / urandom e gpg usa /dev/random está correto.

Você pode assistir a entropia disponível diminuindo enquanto gera chaves com gpg usando:

watch -n 1 cat /proc/sys/kernel/random/entropy_avail

Eu usei um programa para gerar a descrição das etapas para configurar um smart card do OpenGPG com gpg , então tive que executar gpg várias vezes até que tudo funcionasse como pretendido. Após as execuções iniciais, notei que /dev/random não teria entropia suficiente e gpg apenas ficaria esperando que a nova entropia fosse acumulada.

Eu escrevi um pequeno programa para fornecer dados extras não aleatórios, e quando isso foi feito, gpg não "pararia", mas geraria as chaves quase imediatamente: bom para testar o script para rodar corretamente, mas é claro que não é algo que você deve fazer ao gerar suas chaves reais.

O programa para acelerar gpg ( não use em situações reais ):

# For testing purposes only 
# DO NOT USE THIS, tHIS DOES NOT PROVIDE ENTROPY TO /dev/random

import fcntl
import time
import struct

RNDADDENTROPY=0x40085203

while True:
    random = "3420348024823049823-984230942049832423l4j2l42j"
    t = struct.pack("ii32s", 8, 32, random)
    with open("/dev/random", mode='wb') as fp:
        # as fp has a method fileno(), you can pass it to ioctl
        res = fcntl.ioctl(fp, RNDADDENTROPY, t)
        time.sleep(0.001)

Quando executo isso enquanto assisto entropy_avail , posso ver a entropia disponível subir para mais de 3800.

    
por 16.03.2014 / 16:35