Procedura corretta per la crittografia dei dati con chiave pubblica e password che protegge la chiave privata

2

Mi vedo nella necessità di usare PKI in un programma su Linux.

Il seguente codice riassume l'approccio che prendo.

Genera una coppia di chiavi, memorizzala su disco. La chiave privata è crittografata con AES per la crittografia a riposo (anche la chiave privata non crittografata viene archiviata a scopo di test)

Questo riflette gli standard correnti della comunità di sicurezza?

import os
import json
import base64
import getpass
from Cryptodome.Cipher import AES
from Cryptodome.PublicKey import RSA

print '################################################'

if True:
  PASSWORD = '01234567'[:32].ljust(32)
else:
  print 'Enter password (max 32 chars)'
  PASSWORD = getpass.getpass()[:32].ljust(32)

print '################################################'

GENERATE = False
if not os.path.isfile('private-key-2048.pem.encrypted'):
  GENERATE = True
  print 'GENERATING KEY PAIR'

print '################################################'
print '   CREATE / LOAD THE PRIVATE KEY'
print '################################################'

if GENERATE:

  # store the private key
  private_key = RSA.generate(2048)

  with open('private-key-2048.pem','wb') as f:
    f.write(private_key.exportKey('PEM'))

  with open('private-key-2048.pem.encrypted','wb') as f:
    cipher = AES.new(PASSWORD, AES.MODE_EAX)
    ciphertext, tag = cipher.encrypt_and_digest(private_key.exportKey('PEM'))
    print repr(tag)
    f.write(json.dumps({
        'ciphertext': base64.b64encode(ciphertext),
        'nonce': base64.b64encode(cipher.nonce),
        'tag': base64.b64encode(tag)
      }, indent=1))

else:

  # already generated, read the private key
  private_key = RSA.importKey(open('private-key-2048.pem','rb').read())
  with open('private-key-2048.pem.encrypted','rb') as f:
    data = json.loads(f.read())
    cipher = AES.new(PASSWORD, AES.MODE_EAX, base64.b64decode(data['nonce']))
    ciphertext = cipher.decrypt(base64.b64decode(data['ciphertext']))
    try:
      cipher.verify(base64.b64decode(data['tag']))
    except ValueError:
      print 'password incorrect or message corrupted'
  private_key = RSA.importKey(ciphertext)

print private_key.exportKey('PEM')

print '################################################'
print '   SAVE / LOAD THE PUBLIC KEY'
print '################################################'

if GENERATE:

  # store the public key      
  public_key = private_key.publickey()
  with open('public-key-2048.pem','wb') as f:
    f.write(public_key.exportKey('PEM'))

else:

  # already generated, read the public key      
  public_key = RSA.importKey(open('public-key-2048.pem','rb').read())

print public_key.exportKey('PEM')


print '################################################'
print '   ENCRYPT WITH PUBLIC KEY'
print '################################################'


from Cryptodome.Cipher import PKCS1_OAEP
encryptor = PKCS1_OAEP.new(public_key)
encrypted = encryptor.encrypt('this is a test')
print repr(encrypted)

print '################################################'
print '   DECRYPT WITH PRIVATE KEY'
print '################################################'

decryptor = PKCS1_OAEP.new(private_key)
decrypted = decryptor.decrypt(encrypted)
print decrypted

print '################################################'
    
posta Daniel F 28.02.2018 - 16:52
fonte

2 risposte

1

Qual è il sistema operativo di destinazione?

Ho appena letto su DPAPI di Windows che viene utilizzato per questo processo e il modo in cui è fatto si basa sulla chiave master e sulla passphrase dell'utente corrente per generare materiale chiave. Quindi utilizza una funzione di allungamento dei tasti per produrre la chiave mancante alla tua, ma aggiungi la passphrase direttamente nell'AES e limitala a 32 caratteri.

O se il tuo obiettivo è Windows usa semplicemente DPAPI direct per proteggere le tue chiavi.

    
risposta data 01.03.2018 - 02:45
fonte
1

Generalmente il metodo di generazione delle chiavi e di protezione della chiave privata con una password è comunemente usato. Fin qui tutto bene.

Tuttavia, non è consigliabile utilizzare il proprio schema per la crittografia. Ci sono state molte vulnerabilità causate da questo.

La maggior parte dei sistemi è in grado di gestire alcuni dei metodi di crittografia a chiave privata standard, il che garantisce ad esempio che la chiave derivata dalla password utilizza una buona funzione di derivazione della chiave. I due metodi più comuni che conosco sono PKCS # 12, usato da Windows, browser, ecc. E PEM, come usato da OpenSSL.

L'utilizzo di uno di questi metodi ti renderà più facile. Sarà probabilmente più sicuro, sarete interoperabili con i sistemi standard e sarete facilmente in grado di effettuare il porting del codice tra diversi linguaggi di programmazione semplicemente cercando come utilizzare questo standard specifico nella nuova lingua.

    
risposta data 05.04.2018 - 08:05
fonte

Leggi altre domande sui tag