See also: http://tools.ietf.org/html/rfc4880
 public static function encrypt($passphrases_and_keys, $message, $symmetric_algorithm = 9)
 {
     list($cipher, $key_bytes, $key_block_bytes) = self::getCipher($symmetric_algorithm);
     if (!$cipher) {
         throw new Exception("Unsupported cipher");
     }
     $prefix = crypt_random_string($key_block_bytes);
     $prefix .= substr($prefix, -2);
     $key = crypt_random_string($key_bytes);
     $cipher->setKey($key);
     $to_encrypt = $prefix . $message->to_bytes();
     $mdc = new OpenPGP_ModificationDetectionCodePacket(hash('sha1', $to_encrypt . "Ó", true));
     $to_encrypt .= $mdc->to_bytes();
     $encrypted = array(new OpenPGP_IntegrityProtectedDataPacket($cipher->encrypt($to_encrypt)));
     if (!is_array($passphrases_and_keys) && !$passphrases_and_keys instanceof IteratorAggregate) {
         $passphrases_and_keys = (array) $passphrases_and_keys;
     }
     foreach ($passphrases_and_keys as $pass) {
         if ($pass instanceof OpenPGP_PublicKeyPacket) {
             if (!in_array($pass->algorithm, array(1, 2, 3))) {
                 throw new Exception("Only RSA keys are supported.");
             }
             $crypt_rsa = new OpenPGP_Crypt_RSA($pass);
             $rsa = $crypt_rsa->public_key();
             $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
             $esk = $rsa->encrypt(chr($symmetric_algorithm) . $key . pack('n', self::checksum($key)));
             $esk = pack('n', OpenPGP::bitlength($esk)) . $esk;
             array_unshift($encrypted, new OpenPGP_AsymmetricSessionKeyPacket($pass->algorithm, $pass->fingerprint(), $esk));
         } else {
             if (is_string($pass)) {
                 $s2k = new OpenPGP_S2K(crypt_random_string(10));
                 $cipher->setKey($s2k->make_key($pass, $key_bytes));
                 $esk = $cipher->encrypt(chr($symmetric_algorithm) . $key);
                 array_unshift($encrypted, new OpenPGP_SymmetricSessionKeyPacket($s2k, $esk, $symmetric_algorithm));
             }
         }
     }
     return new OpenPGP_Message($encrypted);
 }
示例#2
0
文件: Armor.php 项目: horde/horde
 /**
  */
 public function next()
 {
     $base64 = true;
     $class = $end = $end_armor = $ob_class = $start = null;
     $headers = array();
     $stream = $this->_data;
     while (!($eof = $stream->eof())) {
         $pos = $stream->pos();
         $val = rtrim($stream->getToChar("\n", !is_null($start)));
         if (is_null($end_armor) && strpos($val, '-----BEGIN PGP ') === 0 && substr($val, -5) === '-----') {
             $armor = substr($val, 15, strpos($val, '-', 15) - 15);
             if ($start) {
                 $stream->seek($pos, false);
                 break;
             }
             switch ($armor) {
                 case 'MESSAGE':
                     $class = 'Horde_Pgp_Element_Message';
                     break;
                 case 'PUBLIC KEY BLOCK':
                     $class = 'Horde_Pgp_Element_PublicKey';
                     break;
                 case 'PRIVATE KEY BLOCK':
                     $class = 'Horde_Pgp_Element_PrivateKey';
                     break;
                 case 'SIGNATURE':
                     $class = 'Horde_Pgp_Element_Signature';
                     break;
                 case 'SIGNED MESSAGE':
                     $armor = 'SIGNATURE';
                     $base64 = false;
                     $class = 'Horde_Pgp_Element_SignedMessage';
                     break;
                 default:
                     /* Unknown: ignore. */
                     continue 2;
             }
             $end_armor = '-----END PGP ' . $armor . '-----';
         } elseif (!is_null($end_armor)) {
             if (is_null($start)) {
                 if (strlen($val)) {
                     list($h, $v) = explode(':', $val, 2);
                     $headers[trim($h)] = trim($v);
                 } else {
                     $start = $stream->pos();
                 }
             } elseif ($val === $end_armor) {
                 $end = $pos;
                 $ob_class = $class;
                 break;
             }
         }
     }
     if ($eof && (is_null($this->_key) || is_null($start))) {
         $this->_current = $this->_key = null;
         return;
     }
     if (is_null($ob_class)) {
         $ob_class = 'Horde_Pgp_Element_Text';
     }
     $pos = $stream->pos();
     $data = $stream->getString($start, $end - 1);
     $stream->seek($pos, false);
     if ($base64) {
         /* Get checksum, if it exists. */
         if ($pos = strrpos($data, "\n=")) {
             $checksum = base64_decode(substr($data, $pos + 2, 4));
             $data = base64_decode(substr($data, 0, $pos));
             Horde_Pgp_Backend_Openpgp::autoload();
             $data_checksum = substr(pack('N', OpenPGP::crc24($data)), 1);
             if ($data_checksum !== $checksum) {
                 // Checksum error!
                 return $this->next();
             }
         } else {
             $data = base64_decode($data);
         }
     }
     $this->_current = new $ob_class($data, $headers);
     $this->_key = is_null($this->_key) ? 0 : $this->_key + 1;
 }
示例#3
0
 function body()
 {
     $bytes = parent::body() . chr($this->s2k_useage);
     $secret_material = NULL;
     if ($this->s2k_useage == 255 || $this->s2k_useage == 254) {
         $bytes .= chr($this->symmetric_algorithm);
         $bytes .= $this->s2k->to_bytes();
     }
     if ($this->s2k_useage > 0) {
         $bytes .= $this->encrypted_data;
     } else {
         $secret_material = '';
         foreach (self::$secret_key_fields[$this->algorithm] as $f) {
             $f = $this->key[$f];
             $secret_material .= pack('n', OpenPGP::bitlength($f));
             $secret_material .= $f;
         }
         $bytes .= $secret_material;
         // 2-octet checksum
         $chk = 0;
         for ($i = 0; $i < strlen($secret_material); $i++) {
             $chk = ($chk + ord($secret_material[$i])) % 65536;
         }
         $bytes .= pack('n', $chk);
     }
     return $bytes;
 }
示例#4
0
 /**
  * @see http://tools.ietf.org/html/rfc4880#section-12.2
  * @see http://tools.ietf.org/html/rfc4880#section-3.3
  */
 function fingerprint()
 {
     switch ($this->version) {
         case 2:
         case 3:
             return $this->fingerprint = md5($this->key['n'] . $this->key['e']);
         case 4:
             $head = array(chr(0x99), NULL, chr($this->version), pack('N', $this->timestamp), chr($this->algorithm));
             $material = array();
             foreach ($this->key as $data) {
                 $material[] = pack('n', OpenPGP::bitlength($data));
                 $material[] = $data;
             }
             $material = implode('', $material);
             $head[1] = pack('n', 6 + strlen($material));
             return $this->fingerprint = sha1(implode('', $head) . $material);
     }
 }
示例#5
0
<?php

// USAGE: php examples/deASCIIdeCrypt.php secretkey.asc password message.asc
// This will fail if the algo on key or message is not 3DES or AES
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';
$keyASCII = file_get_contents($argv[1]);
$msgASCII = file_get_contents($argv[3]);
$keyEncrypted = OpenPGP_Message::parse(OpenPGP::unarmor($keyASCII, 'PGP PRIVATE KEY BLOCK'));
// Try each secret key packet
foreach ($keyEncrypted as $p) {
    if (!$p instanceof OpenPGP_SecretKeyPacket) {
        continue;
    }
    $key = OpenPGP_Crypt_Symmetric::decryptSecretKey($argv[2], $p);
    $msg = OpenPGP_Message::parse(OpenPGP::unarmor($msgASCII, 'PGP MESSAGE'));
    $decryptor = new OpenPGP_Crypt_RSA($key);
    $decrypted = $decryptor->decrypt($msg);
    var_dump($decrypted);
}
示例#6
0
文件: Element.php 项目: horde/horde
 /**
  */
 public function __toString()
 {
     $bytes = $this->message->to_bytes();
     if (!strlen($this->_armor)) {
         return $bytes;
     }
     return OpenPGP::enarmor($bytes, 'PGP ' . $this->_armor, array_merge($this->headers, array('Version' => $this->armorVersion)));
 }
示例#7
0
<?php

require_once dirname(__FILE__) . '/../lib/openpgp.php';
require_once dirname(__FILE__) . '/../lib/openpgp_crypt_rsa.php';
/* Parse secret key from STDIN, the key must not be password protected */
$wkey = OpenPGP_Message::parse(file_get_contents('php://stdin'));
$wkey = $wkey[0];
$string = "This\nis\na\ntest.";
/* Create a new literal data packet */
$data = new OpenPGP_LiteralDataPacket($string, array('format' => 'u', 'filename' => 'stuff.txt'));
$data->normalize(true);
// Clearsign-style normalization of the LiteralDataPacket
/* Create a signer from the key */
$sign = new OpenPGP_Crypt_RSA($wkey);
/* The message is the signed data packet */
$m = $sign->sign($data);
/* Generate clearsigned data */
$packets = $m->signatures()[0];
echo "-----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA256\n\n";
// Output normalised data.  You could convert line endings here
// without breaking the signature, but do not add any
// trailing whitespace to lines.
echo preg_replace("/^-/", "- -", $packets[0]->data) . "\n";
echo OpenPGP::enarmor($packets[1][0]->to_bytes(), "PGP SIGNATURE");
示例#8
0
 /**
  * Encrypt data.
  *
  * @param mixed $key   The list of public keys used to encrypt or a list
  *                     of passphrases.
  * @param mixed $data  The data to be PGP encrypted.
  * @param array $opts  Additional options:
  *   - cipher: (integer) Cipher algorithm.
  *   - compress: (integer) Compression algorithm.
  *
  * @param Horde_Pgp_Element_Message  Encrypted message.
  */
 protected function _encrypt($key, $data, $opts)
 {
     $msg = $this->_compressMessageOb($this->_getMessageOb($data), $opts['compress']);
     /* Following code adapted from OpenPGP_Crypt_Symmetric::encrypt(). */
     list($cipher, $key_bytes, $block_bytes) = OpenPGP_Crypt_Symmetric::getCipher($opts['cipher']);
     $prefix = crypt_random_string($block_bytes);
     $prefix .= substr($prefix, -2);
     $to_encrypt = $prefix . $msg->to_bytes();
     $mdc = new OpenPGP_ModificationDetectionCodePacket(hash('sha1', $to_encrypt . "Ó", true));
     /* This is the symmetric encryption session key. */
     $ckey = crypt_random_string($key_bytes);
     $cipher->setKey($ckey);
     /* This is the symmetrically encrypted version of plaintext. */
     $encrypted = array(new OpenPGP_IntegrityProtectedDataPacket($cipher->encrypt($to_encrypt . $mdc->to_bytes())));
     /* Now we need to encrypt the symmetric session key into the various
      * session key encrypted entities. */
     foreach ($key as $k) {
         /* Symmetric encryption. */
         if (is_string($k)) {
             $s2k = new OpenPGP_S2K(crypt_random_string(8, 2));
             // SHA-1
             $cipher->setKey($s2k->make_key($k, $key_bytes));
             $encrypted[] = new OpenPGP_SymmetricSessionKeyPacket($s2k, $cipher->encrypt(chr($opts['cipher']) . $ckey), $opts['cipher']);
             continue;
         }
         /* Public key encryption. */
         switch ($k->algorithm) {
             case 1:
             case 2:
             case 3:
                 $rsa = new OpenPGP_Crypt_RSA($k);
                 $pk = $rsa->public_key();
                 $pk->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
                 break;
             case 16:
                 $pk = new Horde_Pgp_Crypt_Elgamal($k);
                 break;
         }
         $pk_encrypt = $pk->encrypt(chr($opts['cipher']) . $ckey . pack('n', OpenPGP_Crypt_Symmetric::checksum($ckey)));
         $esk = array();
         foreach (is_array($pk_encrypt) ? $pk_encrypt : array($pk_encrypt) as $val) {
             $esk[] = pack('n', OpenPGP::bitlength($val)) . $val;
         }
         $encrypted[] = new OpenPGP_AsymmetricSessionKeyPacket($k->algorithm, $k->fingerprint(), implode('', $esk));
     }
     return new Horde_Pgp_Element_Message(new OpenPGP_Message(array_reverse($encrypted)));
 }
 public function signDocument()
 {
     $document = new \StdClass();
     foreach ($this->resourceData as $term => $value) {
         $document->{$term} = $this->normalizeData($value);
     }
     unset($document->digital_signature);
     unset($document->_id);
     unset($document->_rev);
     unset($document->doc_id);
     unset($document->publishing_node);
     unset($document->update_timestamp);
     unset($document->node_timestamp);
     unset($document->create_timestamp);
     $bencoder = new \LearningRegistry\Bencode\LearningRegistryBencodeEncoderTrial();
     $document = (array) $document;
     $bencodedDocument = utf8_encode($bencoder->encode($document));
     $hashedDocument = hash('SHA256', $bencodedDocument);
     global $loader;
     if (!isset($loader)) {
         $loader = $this->getLoader();
     }
     spl_autoload_unregister(array($loader, 'loadClass'));
     require_once dirname(__FILE__) . '/../OpenPGP/openpgp.php';
     require_once dirname(__FILE__) . '/../OpenPGP/openpgp_crypt_rsa.php';
     require_once dirname(__FILE__) . '/../OpenPGP/openpgp_crypt_symmetric.php';
     $keyASCII = $this->getKey();
     $keyEncrypted = \OpenPGP_Message::parse(\OpenPGP::unarmor($keyASCII, 'PGP PRIVATE KEY BLOCK'));
     foreach ($keyEncrypted as $p) {
         if (!$p instanceof \OpenPGP_SecretKeyPacket) {
             continue;
         }
         $key = \OpenPGP_Crypt_Symmetric::decryptSecretKey($this->getPassPhrase(), $p);
     }
     $data = new \OpenPGP_LiteralDataPacket($hashedDocument, array('format' => 'u'));
     $sign = new \OpenPGP_Crypt_RSA($key);
     $m = $sign->sign($data);
     $packets = $m->signatures()[0];
     $message = "-----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA256\n\n";
     $message .= $packets[0]->data . "\n";
     $message .= "-----BEGIN PGP SIGNATURE-----\n\n";
     $signed_data = str_replace("-----BEGIN -----", "", str_replace("-----END -----", "", \OpenPGP::enarmor($packets[1][0]->to_bytes(), "")));
     $signature = str_split(trim($signed_data), 65);
     foreach ($signature as $line) {
         $message .= $line . "\n";
     }
     $message .= "-----END PGP SIGNATURE-----\n";
     $this->setSigFields(array('signature' => $message, 'key_owner' => $this->getKeyOwner(), 'key_location' => array($this->getPublicKeyPath()), 'signing_method' => "LR-PGP.1.0"));
     spl_autoload_register(array($loader, 'loadClass'));
     $this->document = $this->createDocument();
 }