Implement encryptSecretKey
Allow encrypting a decrypted secret key, which is especially useful for generating a new encrypted secret key. Defaults to AES256, S2K iter+salt SHA512, always uses s2k_useage 254 with sha1 integrity protection of the encrypted key material. Also add an example to parallel keygen.php that generates a key and then encrypts it with a passphrase.
This commit is contained in:
parent
67aba78699
commit
d27d30a352
28
examples/keygenEncrypted.php
Normal file
28
examples/keygenEncrypted.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
@include_once dirname(__FILE__).'/../vendor/autoload.php';
|
||||
require_once dirname(__FILE__).'/../lib/openpgp.php';
|
||||
require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
|
||||
require_once dirname(__FILE__).'/../lib/openpgp_crypt_symmetric.php';
|
||||
|
||||
$rsa = new \phpseclib\Crypt\RSA();
|
||||
$k = $rsa->createKey(512);
|
||||
$rsa->loadKey($k['privatekey']);
|
||||
|
||||
$nkey = new OpenPGP_SecretKeyPacket(array(
|
||||
'n' => $rsa->modulus->toBytes(),
|
||||
'e' => $rsa->publicExponent->toBytes(),
|
||||
'd' => $rsa->exponent->toBytes(),
|
||||
'p' => $rsa->primes[2]->toBytes(),
|
||||
'q' => $rsa->primes[1]->toBytes(),
|
||||
'u' => $rsa->coefficients[2]->toBytes()
|
||||
));
|
||||
|
||||
$uid = new OpenPGP_UserIDPacket('Test <test@example.com>');
|
||||
|
||||
$wkey = new OpenPGP_Crypt_RSA($nkey);
|
||||
$m = $wkey->sign_key_userid(array($nkey, $uid));
|
||||
$m[0] = OpenPGP_Crypt_Symmetric::encryptSecretKey("password", $nkey);
|
||||
|
||||
// Serialize encrypted private key
|
||||
print $m->to_bytes();
|
@ -75,6 +75,31 @@ class OpenPGP_Crypt_Symmetric {
|
||||
return NULL; /* If we get here, we failed */
|
||||
}
|
||||
|
||||
public static function encryptSecretKey($pass, $packet, $symmetric_algorithm=9) {
|
||||
$packet = clone $packet; // Do not mutate original
|
||||
$packet->s2k_useage = 254;
|
||||
$packet->symmetric_algorithm = $symmetric_algorithm;
|
||||
|
||||
list($cipher, $key_bytes, $key_block_bytes) = self::getCipher($packet->symmetric_algorithm);
|
||||
if(!$cipher) throw new Exception("Unsupported cipher");
|
||||
|
||||
$material = '';
|
||||
foreach(OpenPGP_SecretKeyPacket::$secret_key_fields[$packet->algorithm] as $field) {
|
||||
$f = $packet->key[$field];
|
||||
$material .= pack('n', OpenPGP::bitlength($f)) . $f;
|
||||
unset($packet->key[$field]);
|
||||
}
|
||||
$material .= hash('sha1', $material, true);
|
||||
|
||||
$iv = Random::string($key_block_bytes);
|
||||
if(!$packet->s2k) $packet->s2k = new OpenPGP_S2K(Random::string(8));
|
||||
$cipher->setKey($packet->s2k->make_key($pass, $key_bytes));
|
||||
$cipher->setIV($iv);
|
||||
$packet->encrypted_data = $iv . $cipher->encrypt($material);
|
||||
|
||||
return $packet;
|
||||
}
|
||||
|
||||
public static function decryptSecretKey($pass, $packet) {
|
||||
$packet = clone $packet; // Do not mutate orinigal
|
||||
|
||||
@ -97,6 +122,7 @@ class OpenPGP_Crypt_Symmetric {
|
||||
if($chk != $mkChk) return NULL;
|
||||
}
|
||||
|
||||
$packet->s2k = NULL;
|
||||
$packet->s2k_useage = 0;
|
||||
$packet->symmetric_algorithm = 0;
|
||||
$packet->encrypted_data = NULL;
|
||||
|
@ -143,6 +143,13 @@ class Decryption extends PHPUnit_Framework_TestCase {
|
||||
$this->assertSame(!!$skey, true);
|
||||
}
|
||||
|
||||
public function testEncryptSecretKeyRoundtrip() {
|
||||
$key = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/helloKey.gpg'));
|
||||
$enkey = OpenPGP_Crypt_Symmetric::encryptSecretKey("password", $key[0]);
|
||||
$skey = OpenPGP_Crypt_Symmetric::decryptSecretKey("password", $enkey);
|
||||
$this->assertEquals($key[0], $skey);
|
||||
}
|
||||
|
||||
public function testAlreadyDecryptedSecretKey() {
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage("Data is already unencrypted");
|
||||
|
Loading…
Reference in New Issue
Block a user