55 Commits
0.2.0 ... 0.4.0

Author SHA1 Message Date
Stephen Paul Weber
67aba78699 Bump to 0.4.0 2019-08-01 13:11:09 -05:00
Stephen Paul Weber
c0e6aeb163 Remove support for hhvm
Closes #79
2019-04-30 19:05:28 -05:00
Stephen Paul Weber
5e6a097677 Merge pull request #76 from meitar/docs
Provide more guidance for understanding the examples.
2019-03-28 21:19:25 -05:00
Meitar M
f8e0e997fc Provide more guidance for understanding examples, update .travis.yml.
This commit adds an `example/README.md` file with a little bit of
guidance for running the examples themselves. This is helpful because
the examples all rely on the presence of a `phpseclib` installation
available to the PHP interpreter, and while there is a `composer.json`
file to this effect, none of the examples included the Composer
`autoload.php` file.

This commit makes no modifications to the example code itself, but does
`include_once()` the Composer autoload script so that `phpseclib` loads
and avoids causing a fatal error when a new user attempts to run the
examples to learn how to use the library.

This commit also updates the Travis `before_script` build script, dropping
the `--dev` argument to the `composer install` command. Current versions
of Composer emit a deprecation notice when `--dev` is passed.
2018-12-20 13:42:15 -07:00
Stephen Paul Weber
fb671e183d Wordwrap enarmor output
Closes #74
2018-11-20 20:22:24 -05:00
Stephen Paul Weber
f43fbdc053 Put version into code
In case anyone wants to check it, I guess?

Closes #12
2018-07-25 20:18:44 -05:00
Stephen Paul Weber
cd33ba1af1 Upstream isn't coming back 2018-07-25 19:26:57 -05:00
Stephen Paul Weber
34ffc765ec Merge pull request #62 from Rotzbua/patch-2
add travis build status to readme
2018-07-25 19:13:50 -05:00
Stephen Paul Weber
752d80f14a S2K salt is *always* 8 bytes
Closes #33
2018-07-25 15:04:49 -05:00
Stephen Paul Weber
575baaf3f2 Set up Travis to check combinations that all work 2018-07-25 14:45:16 -05:00
Stephen Paul Weber
aeb919abc3 Whitespace 2018-07-25 14:37:07 -05:00
Stephen Paul Weber
cba1ecce8a Do not rely on asserts for behaviour
Closes #35
2018-07-25 14:35:51 -05:00
Stephen Paul Weber
f2e1710da5 Tell composer what versions of PHP we test against
Closes #61
2018-07-25 14:16:18 -05:00
Stephen Paul Weber
44e1bb2902 Do not throw when CAST5 unsupported
While this message may be more helpful, it will break some cases, such
as when there are multiple ciphers that could be used and we can just
skip CAST5 and move on.  Return NULL when CAST5 unsupported, just like
for other unsupported ciphers.
2018-07-25 14:08:00 -05:00
Stephen Paul Weber
43497a15c0 Use OpenSSL for CAST5
Mcrypt is deprecated, so use OpenSSL when we can, mcrypt when we can't.
2018-07-25 14:08:00 -05:00
Stephen Paul Weber
5a6b605710 Support Twofish and Blowfish 2018-07-25 14:07:16 -05:00
Stephen Paul Weber
d756110821 Test support for all newer versions of phpseclib
It seems only 2.0.8 is broken
2018-07-25 11:06:11 -05:00
Stephen Paul Weber
724d5b16f3 Newer phpunit can't support older PHP
They're very old, and 5.6 is available in Debian stable and oldstable,
so drop support.
2018-07-25 10:31:52 -05:00
Stephen Paul Weber
26560f7bca Upgrade phpunit version to use in Travis 2018-07-25 10:27:30 -05:00
Stephen Paul Weber
498e60602b If session decryption fails, return NULL
Otherwise it returns false, we try to unpack that, and generally bad
things happen.
2018-07-25 09:57:33 -05:00
Stephen Paul Weber
413741fa84 Throw more helpful exception when already decrypted 2018-07-25 09:56:57 -05:00
Stephen Paul Weber
a9fc3f9322 Merge pull request #64 from Rotzbua/Rotzbua-patch-2
add suggestion to composer
2018-07-25 09:00:09 -05:00
Stephen Paul Weber
facaaa4dbb Merge pull request #63 from Rotzbua/Rotzbua-patch-1
add php 7.1 7.2 to travis
2017-12-26 18:11:29 -05:00
Rotzbua
ba3c3fd42d add suggestion to composer 2017-12-26 21:53:31 +01:00
Rotzbua
ebce9c014c add travis build status to reamde 2017-12-15 16:37:53 +01:00
Rotzbua
f42afa0ca3 Update .travis.yml 2017-12-15 16:35:33 +01:00
Rotzbua
e8a56241a5 Update .travis.yml 2017-12-15 16:30:18 +01:00
Rotzbua
69d935435c add php 7.1 7.2 2017-12-15 16:10:39 +01:00
Stephen Paul Weber
541328576a Merge pull request #60 from Rotzbua/patch-1
[doc] change links to https
2017-12-15 09:28:05 -05:00
Rotzbua
a8e7690a69 change links to https 2017-12-15 15:23:00 +01:00
Stephen Paul Weber
c9ae8251b6 New list of supported PHPs on Travis 2017-07-22 17:03:04 -05:00
Stephen Paul Weber
95facfb57f Travis wants trusty for HHVM now 2017-07-18 19:35:20 -05:00
Stephen Paul Weber
6006111bbc Bump version number 2017-04-12 16:23:15 -05:00
Stephen Paul Weber
2561004fcd Merge pull request #46 from jasekiw/master
https://github.com/phpseclib/phpseclib/issues/1113
2017-04-11 09:19:35 -05:00
Jason Gallavin
cea5b176fc https://github.com/phpseclib/phpseclib/issues/1113
Add compatibility with phpseclib 2.0.3 - 2.0.4
2017-04-10 22:28:54 -04:00
Stephen Paul Weber
a61fb279c3 Merge pull request #45 from singpolyma/new-phpseclib-breaks-us
Seems phpseclib 2.0.3 breaks us
2017-04-08 11:38:02 -05:00
Stephen Paul Weber
7538c62edd Seems phpseclib 2.0.3 breaks us 2017-04-08 11:25:33 -05:00
Stephen Paul Weber
741fec24a6 These coefficients go in the other order 2016-07-26 20:09:15 -05:00
Stephen Paul Weber
4531815ef2 The code in fact expects an array of OR'd bytes
As the spec specifies.

Closes #32
2016-07-26 19:21:57 -05:00
Stephen Paul Weber
46ec5079e8 Only env can matrix 2016-07-26 19:10:18 -05:00
Stephen Paul Weber
02fbcbf7e6 nightly not working, can't find docs on the deprecation yet 2016-07-26 18:59:02 -05:00
Stephen Paul Weber
6d9ed34224 Less strict phpseclib requirement
Still test against 2.0.0 as well as latest
2016-07-26 18:58:16 -05:00
Stephen Paul Weber
de41f143e6 Throw exception if using CAST5 without mcrypt 2016-07-26 18:44:49 -05:00
Stephen Paul Weber
859efcbee3 Merge pull request #28 from DanielRuf/patch-2
use $cipher->key_length
2016-03-15 08:23:47 -04:00
Stephen Paul Weber
15baf1db70 Merge pull request #29 from DanielRuf/patch-3
added more PHP versions to the travis file
2016-03-15 08:23:18 -04:00
Daniel Ruf
a87e6ac0c9 added more PHP versions to the travis file
5.3 and 5.4 could be possibly removed. Nightly builds and HHVM should be ok.
2016-03-15 09:31:57 +01:00
Daniel Ruf
08ae2c57d1 use $cipher->key_length
starting with phpseclib 2.0.1, `key_size` was renamed to `key_length`
2016-03-14 12:10:17 +01:00
Stephen Paul Weber
cefaef242d Update normalise and example for clearsigning
Trailing whitespace must be removed when generating the signature and
must not be included in output.
2016-02-24 11:07:10 -05:00
Stephen Paul Weber
6340379ffe Merge pull request #24 from DanielRuf/patch-1
fixed keygen example for the phpseclib 2.0 branch
2016-02-24 10:27:45 -05:00
Daniel Ruf
bcc9c920a0 fixed keygen example for the phpseclib 2.0 branch
Starting with phpseclib 2.0, it is fully namespaced and we have to use the fully qualified name.
2016-02-23 20:33:23 +01:00
Stephen Paul Weber
57ab2811c4 Merge pull request #22 from meitar/new-consumer
Link to new project that uses OpenPGP.php as library.
2016-02-20 21:16:43 -05:00
Meitar Moscovitz
b260774147 Link to new project that uses OpenPGP.php as library. 2016-02-20 17:17:53 -07:00
Stephen Paul Weber
a1fe3a6e58 Merge pull request #16 from sivig/phpseclib-2
use phpseclib 2.0
2015-11-30 14:49:15 -05:00
Vitaliy Solovey
ff4bd67e6b use phpseclib 2.0 2015-11-20 11:39:37 +02:00
Stephen Paul Weber
d37e91efda Example to serialize public key message 2015-11-16 10:40:44 -05:00
19 changed files with 427 additions and 164 deletions

View File

@@ -1,6 +1,51 @@
---
language: php
php:
- "5.4"
- "5.3"
before_script:
- composer install --prefer-source --dev
- 7.0
- 7.1
- 7.2
- 5.6
dist: trusty
env:
- PHPSECLIB='^2.0 !=2.0.8'
- PHPSECLIB="2.0.0"
- PHPSECLIB="2.0.1"
- PHPSECLIB="2.0.2"
- PHPSECLIB="2.0.3"
- PHPSECLIB="2.0.4"
- PHPSECLIB="2.0.5"
- PHPSECLIB="2.0.6"
- PHPSECLIB="2.0.7"
- PHPSECLIB="2.0.9"
- PHPSECLIB="2.0.10"
- PHPSECLIB="2.0.11"
matrix:
exclude:
- php: 7.1
- env: PHPSECLIB="2.0.0"
- php: 7.2
- env: PHPSECLIB="2.0.0"
- php: 7.1
- env: PHPSECLIB="2.0.1"
- php: 7.2
- env: PHPSECLIB="2.0.1"
- php: 7.1
- env: PHPSECLIB="2.0.2"
- php: 7.2
- env: PHPSECLIB="2.0.2"
- php: 7.1
- env: PHPSECLIB="2.0.3"
- php: 7.2
- env: PHPSECLIB="2.0.3"
- php: 7.2
- env: PHPSECLIB="2.0.4"
- php: 7.2
- env: PHPSECLIB="2.0.5"
- php: 7.2
- env: PHPSECLIB="2.0.6"
fast_finish: true
before_script: 'sed -i "s/\"phpseclib\/phpseclib\": \"[^\"]*/\"phpseclib\/phpseclib\": \"$PHPSECLIB/" composer.json && composer install --prefer-source'

View File

@@ -1,11 +1,14 @@
[![Build Status](https://travis-ci.org/singpolyma/openpgp-php.svg?branch=master)](https://travis-ci.org/singpolyma/openpgp-php)
OpenPGP.php: OpenPGP for PHP
============================
This is a pure-PHP implementation of the OpenPGP Message Format (RFC 4880).
* <http://github.com/bendiken/openpgp-php>
* <https://github.com/singpolyma/openpgp-php>
### About OpenPGP
About OpenPGP
-------------
OpenPGP is the most widely-used e-mail encryption standard in the world. It
is defined by the OpenPGP Working Group of the Internet Engineering Task
@@ -13,8 +16,8 @@ Force (IETF) Proposed Standard RFC 4880. The OpenPGP standard was originally
derived from PGP (Pretty Good Privacy), first created by Phil Zimmermann in
1991.
* <http://tools.ietf.org/html/rfc4880>
* <http://www.openpgp.org/>
* <https://tools.ietf.org/html/rfc4880>
* <https://www.openpgp.org/>
Features
--------
@@ -22,36 +25,48 @@ Features
* Encodes and decodes ASCII-armored OpenPGP messages.
* Parses OpenPGP messages into their constituent packets.
* Supports both old-format (PGP 2.6.x) and new-format (RFC 4880) packets.
* Helper class for verifying, signing, encrypting, and decrypting messages using Crypt_RSA from <http://phpseclib.sourceforge.net>
* Helper class for encrypting and decrypting messages and keys using Crypt_AES and Crypt_TripleDES from <http://phpseclib.sourceforge.net>
* Helper class for verifying, signing, encrypting, and decrypting messages <http://phpseclib.sourceforge.net>
* Helper class for encrypting and decrypting messages and keys using <http://phpseclib.sourceforge.net>
* openssl or mcrypt required for CAST5 encryption and decryption
Bugs, Feature Requests, Patches
-------------------------------
This project is primarily maintained by a single volunteer with many other
things vying for their attention, please be patient.
Bugs, feature request, pull requests, patches, and general discussion may
be submitted publicly via email to: dev@singpolyma.net
Github users may alternately submit on the web there.
Users
-----
OpenPGP.php is currently being used in the following projects:
* <http://drupal.org/project/openpgp>
* <https://wordpress.org/plugins/wp-pgp-encrypted-emails/>
Download
--------
To get a local working copy of the development repository, do:
% git clone git://github.com/bendiken/openpgp-php.git
git clone https://github.com/singpolyma/openpgp-php.git
Alternatively, you can download the latest development version as a tarball
as follows:
% wget http://github.com/bendiken/openpgp-php/tarball/master
wget https://github.com/singpolyma/openpgp-php/tarball/master
Authors
-------
* [Arto Bendiken](mailto:arto.bendiken@gmail.com) - <http://ar.to/>
* [Stephen Paul Weber](mailto:singpolyma@singpolyma.net) - <http://singpolyma.net/>
* [Arto Bendiken](mailto:arto.bendiken@gmail.com) (Original author) - <http://ar.to/>
* [Stephen Paul Weber](mailto:singpolyma@singpolyma.net) (Maintainer) - <https://singpolyma.net/>
License
-------
OpenPGP.php is free and unencumbered public domain software. For more
information, see <http://unlicense.org/> or the accompanying UNLICENSE file.
information, see <https://unlicense.org/> or the accompanying UNLICENSE file.

View File

@@ -1 +1 @@
0.0.1
0.3.0

View File

@@ -13,10 +13,14 @@
}
],
"require": {
"phpseclib/phpseclib": "~0.3"
"php": "^5.6 || ^7.0",
"phpseclib/phpseclib": "^2.0 !=2.0.8"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
"phpunit/phpunit": "^5.0"
},
"suggest": {
"ext-mcrypt": "required if you use encryption cast5"
},
"autoload": {
"classmap": ["lib/"]

22
examples/README.md Normal file
View File

@@ -0,0 +1,22 @@
OpenPGP.php Examples
====================
The scripts in this folder show how to use this library to perform various tasks
such as [generating a new key](keygen.php), [signing a message](sign.php), and
[verifying a message](verify.php) that has been signed.
To use these examples, make sure [`phpseclib`](http://phpseclib.sourceforge.net/) is available. You can install it
using [Composer](https://getcomposer.org/):
```sh
git clone https://github.com/singpolyma/openpgp-php.git # Clone the repository.
cd openpgp-php
composer install # Use Composer to install the requirements.
```
Once Composer has installed the requirements, run the examples using PHP:
```sh
# Generate a new OpenPGP key; see the `keygen.php` file for parameters.
php ./examples/keygen.php > mykey.gpg
```

View File

@@ -1,5 +1,6 @@
<?php
@include_once dirname(__FILE__).'/../vendor/autoload.php';
require_once dirname(__FILE__).'/../lib/openpgp.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
@@ -7,8 +8,11 @@ require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
$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('This is text.', array('format' => 'u', 'filename' => 'stuff.txt'));
$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);
@@ -19,7 +23,8 @@ $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");
?>

View File

@@ -3,6 +3,7 @@
// 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
@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';

View File

@@ -1,5 +1,6 @@
<?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';

View File

@@ -1,9 +1,10 @@
<?php
@include_once dirname(__FILE__).'/../vendor/autoload.php';
require_once dirname(__FILE__).'/../lib/openpgp.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
$rsa = new Crypt_RSA();
$rsa = new \phpseclib\Crypt\RSA();
$k = $rsa->createKey(512);
$rsa->loadKey($k['privatekey']);
@@ -11,8 +12,8 @@ $nkey = new OpenPGP_SecretKeyPacket(array(
'n' => $rsa->modulus->toBytes(),
'e' => $rsa->publicExponent->toBytes(),
'd' => $rsa->exponent->toBytes(),
'p' => $rsa->primes[1]->toBytes(),
'q' => $rsa->primes[2]->toBytes(),
'p' => $rsa->primes[2]->toBytes(),
'q' => $rsa->primes[1]->toBytes(),
'u' => $rsa->coefficients[2]->toBytes()
));
@@ -21,4 +22,11 @@ $uid = new OpenPGP_UserIDPacket('Test <test@example.com>');
$wkey = new OpenPGP_Crypt_RSA($nkey);
$m = $wkey->sign_key_userid(array($nkey, $uid));
// Serialize private key
print $m->to_bytes();
// Serialize public key message
$pubm = clone($m);
$pubm[0] = new OpenPGP_PublicKeyPacket($pubm[0]);
$public_bytes = $pubm->to_bytes();

View File

@@ -1,5 +1,6 @@
<?php
@include_once dirname(__FILE__).'/../vendor/autoload.php';
require_once dirname(__FILE__).'/../lib/openpgp.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
@@ -18,5 +19,3 @@ $m = $sign->sign($data);
/* Output the raw message bytes to STDOUT */
echo $m->to_bytes();
?>

View File

@@ -1,5 +1,6 @@
<?php
@include_once dirname(__FILE__).'/../vendor/autoload.php';
require_once dirname(__FILE__).'/../lib/openpgp.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
@@ -14,5 +15,3 @@ $verify = new OpenPGP_Crypt_RSA($wkey);
/* Dump verification information to STDOUT */
var_dump($verify->verify($m));
?>

View File

@@ -5,7 +5,7 @@
* (RFC 4880).
*
* @package OpenPGP
* @version 0.0.1
* @version 0.3.0
* @author Arto Bendiken <arto.bendiken@gmail.com>
* @author Stephen Paul Weber <singpolyma@singpolyma.net>
* @see http://github.com/bendiken/openpgp-php
@@ -18,6 +18,8 @@
* @see http://tools.ietf.org/html/rfc4880
*/
class OpenPGP {
const VERSION = array(0, 4, 0);
/**
* @see http://tools.ietf.org/html/rfc4880#section-6
* @see http://tools.ietf.org/html/rfc4880#section-6.2
@@ -28,7 +30,7 @@ class OpenPGP {
foreach ($headers as $key => $value) {
$text .= $key . ': ' . (string)$value . "\n";
}
$text .= "\n" . base64_encode($data);
$text .= "\n" . wordwrap(base64_encode($data), 76, "\n", true);
$text .= "\n".'=' . base64_encode(substr(pack('N', self::crc24($data)), 1)) . "\n";
$text .= self::footer($marker) . "\n";
return $text;
@@ -150,10 +152,12 @@ class OpenPGP_S2K {
$bytes .= chr($this->hash_algorithm);
break;
case 1:
if(strlen($this->salt) != 8) throw new Exception("Invalid salt length");
$bytes .= chr($this->hash_algorithm);
$bytes .= $this->salt;
break;
case 3:
if(strlen($this->salt) != 8) throw new Exception("Invalid salt length");
$bytes .= chr($this->hash_algorithm);
$bytes .= $this->salt;
$bytes .= chr(OpenPGP::encode_s2k_count($this->count));
@@ -685,7 +689,9 @@ class OpenPGP_SignaturePacket extends OpenPGP_Packet {
switch($this->version = ord($this->read_byte())) {
case 2:
case 3:
assert(ord($this->read_byte()) == 5);
if(ord($this->read_byte()) != 5) {
throw new Exception("Invalid version 2 or 3 SignaturePacket");
}
$this->signature_type = ord($this->read_byte());
$creation_time = $this->read_timestamp();
$keyid = $this->read_bytes(8);
@@ -1327,15 +1333,32 @@ class OpenPGP_PublicKeyPacket extends OpenPGP_Packet {
function __construct($key=array(), $algorithm='RSA', $timestamp=NULL, $version=4) {
parent::__construct();
$this->key = $key;
if(is_string($this->algorithm = $algorithm)) {
$this->algorithm = array_search($this->algorithm, self::$algorithms);
}
$this->timestamp = $timestamp ? $timestamp : time();
$this->version = $version;
if(count($this->key) > 0) {
$this->key_id = substr($this->fingerprint(), -8);
if($key instanceof OpenPGP_PublicKeyPacket) {
$this->algorithm = $key->algorithm;
$this->key = array();
// Restrict to only the fields we need
foreach (self::$key_fields[$this->algorithm] as $field) {
$this->key[$field] = $key->key[$field];
}
$this->key_id = $key->key_id;
$this->fingerprint = $key->fingerprint;
$this->timestamp = $key->timestamp;
$this->version = $key->version;
$this->v3_days_of_validity = $key->v3_days_of_validity;
} else {
$this->key = $key;
if(is_string($this->algorithm = $algorithm)) {
$this->algorithm = array_search($this->algorithm, self::$algorithms);
}
$this->timestamp = $timestamp ? $timestamp : time();
$this->version = $version;
if(count($this->key) > 0) {
$this->key_id = substr($this->fingerprint(), -8);
}
}
}
@@ -1685,10 +1708,19 @@ class OpenPGP_LiteralDataPacket extends OpenPGP_Packet {
$this->timestamp = isset($opt['timestamp']) ? $opt['timestamp'] : time();
}
function normalize() {
function normalize($clearsign=false) {
if($clearsign && ($this->format != 'u' && $this->format != 't')) {
$this->format = 'u'; // Clearsign must be text
}
if($this->format == 'u' || $this->format == 't') { // Normalize line endings
$this->data = str_replace("\n", "\r\n", str_replace("\r", "\n", str_replace("\r\n", "\n", $this->data)));
}
if($clearsign) {
// When clearsigning, do not sign over trailing whitespace
$this->data = preg_replace('/\s+\r/', "\r", $this->data);
}
}
function read() {

View File

@@ -7,7 +7,11 @@
*/
// From http://phpseclib.sourceforge.net/
require_once 'Crypt/RSA.php';
use phpseclib\Crypt\RSA as Crypt_RSA;
use phpseclib\Math\BigInteger as Math_BigInteger;
define('CRYPT_RSA_ENCRYPTION_PKCS1', Crypt_RSA::ENCRYPTION_PKCS1);
define('CRYPT_RSA_SIGNATURE_PKCS1', Crypt_RSA::SIGNATURE_PKCS1);
require_once dirname(__FILE__).'/openpgp.php';
@include_once dirname(__FILE__).'/openpgp_crypt_symmetric.php'; /* For encrypt/decrypt */
@@ -150,7 +154,7 @@ class OpenPGP_Crypt_RSA {
if(!$sig) {
$sig = new OpenPGP_SignaturePacket($packet, 'RSA', strtoupper($hash));
$sig->signature_type = 0x13;
$sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_KeyFlagsPacket(array(0x01, 0x02));
$sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_KeyFlagsPacket(array(0x01 | 0x02));
$sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_IssuerPacket($keyid);
$packet[] = $sig;
}
@@ -204,7 +208,8 @@ class OpenPGP_Crypt_RSA {
static function try_decrypt_session($key, $edata) {
$key->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$data = $key->decrypt($edata);
$data = @$key->decrypt($edata);
if(!$data) return NULL;
$sk = substr($data, 1, strlen($data)-3);
$chk = unpack('n', substr($data, -2));
$chk = reset($chk);
@@ -241,8 +246,18 @@ class OpenPGP_Crypt_RSA {
$rsa = self::crypt_rsa_key($mod, $exp);
if($private) {
if($packet->key['p'] && $packet->key['q']) $rsa->primes = array($packet->key['p'], $packet->key['q']);
if($packet->key['u']) $rsa->coefficients = array($packet->key['u']);
/**
* @see https://github.com/phpseclib/phpseclib/issues/1113
* Primes and coefficients now use BigIntegers.
**/
//set the primes
if($packet->key['p'] && $packet->key['q'])
$rsa->primes = array(
1 => new Math_BigInteger($packet->key['p'], 256),
2 => new Math_BigInteger($packet->key['q'], 256)
);
// set the coefficients
if($packet->key['u']) $rsa->coefficients = array(2 => new Math_BigInteger($packet->key['u'], 256));
}
return $rsa;

View File

@@ -1,20 +1,24 @@
<?php
use phpseclib\Crypt\AES as Crypt_AES;
use phpseclib\Crypt\Blowfish as Crypt_Blowfish;
use phpseclib\Crypt\TripleDES as Crypt_TripleDES;
use phpseclib\Crypt\Twofish as Crypt_Twofish;
use phpseclib\Crypt\Random;
require_once dirname(__FILE__).'/openpgp.php';
@include_once dirname(__FILE__).'/openpgp_crypt_rsa.php';
@include_once dirname(__FILE__).'/openpgp_mcrypt_wrapper.php';
@include_once 'Crypt/AES.php';
@include_once 'Crypt/TripleDES.php';
require_once 'Crypt/Random.php'; // part of phpseclib is absolutely required
@include_once dirname(__FILE__).'/openpgp_openssl_wrapper.php';
class OpenPGP_Crypt_Symmetric {
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 = Random::string($key_block_bytes);
$prefix .= substr($prefix, -2);
$key = crypt_random_string($key_bytes);
$key = Random::string($key_bytes);
$cipher->setKey($key);
$to_encrypt = $prefix . $message->to_bytes();
@@ -36,7 +40,7 @@ class OpenPGP_Crypt_Symmetric {
$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));
$s2k = new OpenPGP_S2K(Random::string(8));
$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));
@@ -142,39 +146,49 @@ class OpenPGP_Crypt_Symmetric {
public static function getCipher($algo) {
$cipher = NULL;
switch($algo) {
case NULL:
case 0:
throw new Exception("Data is already unencrypted");
case 2:
if(class_exists('Crypt_TripleDES')) {
$cipher = new Crypt_TripleDES(CRYPT_DES_MODE_CFB);
$key_bytes = 24;
$key_block_bytes = 8;
}
$cipher = new Crypt_TripleDES(Crypt_TripleDES::MODE_CFB);
$key_bytes = 24;
$key_block_bytes = 8;
break;
case 3:
if(defined('MCRYPT_CAST_128')) {
if(class_exists('OpenSSLWrapper')) {
$cipher = new OpenSSLWrapper("CAST5-CFB");
} else if(defined('MCRYPT_CAST_128')) {
$cipher = new MCryptWrapper(MCRYPT_CAST_128);
}
break;
case 4:
$cipher = new Crypt_Blowfish(Crypt_Blowfish::MODE_CFB);
$key_bytes = 16;
$key_block_bytes = 8;
break;
case 7:
if(class_exists('Crypt_AES')) {
$cipher = new Crypt_AES(CRYPT_AES_MODE_CFB);
$cipher->setKeyLength(128);
}
$cipher = new Crypt_AES(Crypt_AES::MODE_CFB);
$cipher->setKeyLength(128);
break;
case 8:
if(class_exists('Crypt_AES')) {
$cipher = new Crypt_AES(CRYPT_AES_MODE_CFB);
$cipher->setKeyLength(192);
}
$cipher = new Crypt_AES(Crypt_AES::MODE_CFB);
$cipher->setKeyLength(192);
break;
case 9:
if(class_exists('Crypt_AES')) {
$cipher = new Crypt_AES(CRYPT_AES_MODE_CFB);
$cipher = new Crypt_AES(Crypt_AES::MODE_CFB);
$cipher->setKeyLength(256);
break;
case 10:
$cipher = new Crypt_Twofish(Crypt_Twofish::MODE_CFB);
if(method_exists($cipher, 'setKeyLength')) {
$cipher->setKeyLength(256);
} else {
$cipher = NULL;
}
break;
}
if(!$cipher) return array(NULL, NULL, NULL); // Unsupported cipher
if(!isset($key_bytes)) $key_bytes = $cipher->key_size;
if(!isset($key_bytes)) $key_bytes = isset($cipher->key_size)?$cipher->key_size:$cipher->key_length;
if(!isset($key_block_bytes)) $key_block_bytes = $cipher->block_size;
return array($cipher, $key_bytes, $key_block_bytes);
}

View File

@@ -0,0 +1,33 @@
<?php
if(function_exists('openssl_encrypt')) {
class OpenSSLWrapper {
public $cipher, $key, $iv, $key_size, $block_size;
function __construct($cipher) {
if($cipher != "CAST5-CFB") throw Exception("OpenSSLWrapper is only used for CAST5 right now");
$this->cipher = $cipher;
$this->key_size = 16;
$this->block_size = 8;
$this->iv = str_repeat("\0", 8);
}
function setKey($key) {
$this->key = $key;
}
function setIV($iv) {
$this->iv = $iv;
}
function encrypt($data) {
return openssl_encrypt($data, $this->cipher, $this->key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $this->iv);
}
function decrypt($data) {
return openssl_decrypt($data, $this->cipher, $this->key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $this->iv);
}
}
}

View File

@@ -0,0 +1 @@
<EFBFBD>

View File

@@ -0,0 +1,3 @@
<EFBFBD>

c<>І <0B><><EFBFBD><EFBFBD><EFBFBD>9=<3D><><EFBFBD><EFBFBD>]<5D>Tf<54>A <0B>c<EFBFBD>v<EFBFBD><76>e<EFBFBD>k<EFBFBD><6B><EFBFBD>ʲ<EFBFBD><CAB2><EFBFBD>n}%.<16>l<16><>u<>?\<5C><>I

View File

@@ -76,18 +76,28 @@ class Decryption extends PHPUnit_Framework_TestCase {
}
}
public function testDecryptAES() {
$this->oneSymmetric("hello", "PGP\n", "symmetric-aes.gpg");
}
public function testDecrypt3DES() {
$this->oneSymmetric("hello", "PGP\n", "symmetric-3des.gpg");
}
public function testDecryptCAST5() { // Requires mcrypt
public function testDecryptCAST5() { // Requires mcrypt or openssl
$this->oneSymmetric("hello", "PGP\n", "symmetric-cast5.gpg");
}
public function testDecryptBlowfish() {
$this->oneSymmetric("hello", "PGP\n", "symmetric-blowfish.gpg");
}
public function testDecryptAES() {
$this->oneSymmetric("hello", "PGP\n", "symmetric-aes.gpg");
}
public function testDecryptTwofish() {
if(OpenPGP_Crypt_Symmetric::getCipher(10)[0]) {
$this->oneSymmetric("hello", "PGP\n", "symmetric-twofish.gpg");
}
}
public function testDecryptSessionKey() {
$this->oneSymmetric("hello", "PGP\n", "symmetric-with-session-key.gpg");
}
@@ -109,25 +119,82 @@ class Decryption extends PHPUnit_Framework_TestCase {
}
}
public function testDecryptRoundtrip() {
$m = new OpenPGP_Message(array(new OpenPGP_LiteralDataPacket("hello\n")));
$key = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/helloKey.gpg'));
$em = OpenPGP_Crypt_Symmetric::encrypt($key, $m);
foreach($key as $packet) {
if(!($packet instanceof OpenPGP_SecretKeyPacket)) continue;
$decryptor = new OpenPGP_Crypt_RSA($packet);
$m2 = $decryptor->decrypt($em);
foreach($m2 as $p) {
if($p instanceof OpenPGP_LiteralDataPacket) {
$this->assertEquals($p->data, "hello\n");
}
}
}
}
public function testDecryptSecretKey() {
$key = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/encryptedSecretKey.gpg'));
$skey = OpenPGP_Crypt_Symmetric::decryptSecretKey("hello", $key[0]);
$this->assertSame(!!$skey, true);
}
public function testAlreadyDecryptedSecretKey() {
$this->expectException(Exception::class);
$this->expectExceptionMessage("Data is already unencrypted");
$key = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/helloKey.gpg'));
OpenPGP_Crypt_Symmetric::decryptSecretKey("hello", $key[0]);
}
}
class Encryption extends PHPUnit_Framework_TestCase {
public function testEncryptSymmetric() {
public function oneSymmetric($algorithm) {
$data = new OpenPGP_LiteralDataPacket('This is text.', array('format' => 'u', 'filename' => 'stuff.txt'));
$encrypted = OpenPGP_Crypt_Symmetric::encrypt('secret', new OpenPGP_Message(array($data)));
$encrypted = OpenPGP_Crypt_Symmetric::encrypt('secret', new OpenPGP_Message(array($data)), $algorithm);
$encrypted = OpenPGP_Message::parse($encrypted->to_bytes());
$decrypted = OpenPGP_Crypt_Symmetric::decryptSymmetric('secret', $encrypted);
$this->assertEquals($decrypted[0]->data, 'This is text.');
}
public function testEncryptSymmetric3DES() {
$this->oneSymmetric(2);
}
public function testEncryptSymmetricCAST5() {
$this->oneSymmetric(3);
}
public function testEncryptSymmetricBlowfish() {
$this->oneSymmetric(4);
}
public function testEncryptSymmetricAES128() {
$this->oneSymmetric(7);
}
public function testEncryptSymmetricAES192() {
$this->oneSymmetric(8);
}
public function testEncryptSymmetricAES256() {
$this->oneSymmetric(9);
}
public function testEncryptSymmetricTwofish() {
if(OpenPGP_Crypt_Symmetric::getCipher(10)[0]) {
$this->oneSymmetric(10);
}
}
public function testEncryptAsymmetric() {
$key = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/helloKey.gpg'));
$data = new OpenPGP_LiteralDataPacket('This is text.', array('format' => 'u', 'filename' => 'stuff.txt'));
$encrypted = OpenPGP_Crypt_Symmetric::encrypt($key, new OpenPGP_Message(array($data)));
$encrypted = OpenPGP_Message::parse($encrypted->to_bytes());
$decryptor = new OpenPGP_Crypt_RSA($key);
$decrypted = $decryptor->decrypt($encrypted);
$this->assertEquals($decrypted[0]->data, 'This is text.');

View File

@@ -14,355 +14,354 @@ class Serialization extends PHPUnit_Framework_TestCase {
$this->oneSerialization("000001-006.public_key");
}
public function test000002013user_id() {
$this->oneSerialization("000002-013.user_id");
}
public function test000003002sig() {
$this->oneSerialization("000003-002.sig");
}
public function test000004012ring_trust() {
$this->oneSerialization("000004-012.ring_trust");
}
public function test000005002sig() {
$this->oneSerialization("000005-002.sig");
}
public function test000006012ring_trust() {
$this->oneSerialization("000006-012.ring_trust");
}
public function test000007002sig() {
$this->oneSerialization("000007-002.sig");
}
public function test000008012ring_trust() {
$this->oneSerialization("000008-012.ring_trust");
}
public function test000009002sig() {
$this->oneSerialization("000009-002.sig");
}
public function test000010012ring_trust() {
$this->oneSerialization("000010-012.ring_trust");
}
public function test000011002sig() {
$this->oneSerialization("000011-002.sig");
}
public function test000012012ring_trust() {
$this->oneSerialization("000012-012.ring_trust");
}
public function test000013014public_subkey() {
$this->oneSerialization("000013-014.public_subkey");
}
public function test000014002sig() {
$this->oneSerialization("000014-002.sig");
}
public function test000015012ring_trust() {
$this->oneSerialization("000015-012.ring_trust");
}
public function test000016006public_key() {
$this->oneSerialization("000016-006.public_key");
}
public function test000017002sig() {
$this->oneSerialization("000017-002.sig");
}
public function test000018012ring_trust() {
$this->oneSerialization("000018-012.ring_trust");
}
public function test000019013user_id() {
$this->oneSerialization("000019-013.user_id");
}
public function test000020002sig() {
$this->oneSerialization("000020-002.sig");
}
public function test000021012ring_trust() {
$this->oneSerialization("000021-012.ring_trust");
}
public function test000022002sig() {
$this->oneSerialization("000022-002.sig");
}
public function test000023012ring_trust() {
$this->oneSerialization("000023-012.ring_trust");
}
public function test000024014public_subkey() {
$this->oneSerialization("000024-014.public_subkey");
}
public function test000025002sig() {
$this->oneSerialization("000025-002.sig");
}
public function test000026012ring_trust() {
$this->oneSerialization("000026-012.ring_trust");
}
public function test000027006public_key() {
$this->oneSerialization("000027-006.public_key");
}
public function test000028002sig() {
$this->oneSerialization("000028-002.sig");
}
public function test000029012ring_trust() {
$this->oneSerialization("000029-012.ring_trust");
}
public function test000030013user_id() {
$this->oneSerialization("000030-013.user_id");
}
public function test000031002sig() {
$this->oneSerialization("000031-002.sig");
}
public function test000032012ring_trust() {
$this->oneSerialization("000032-012.ring_trust");
}
public function test000033002sig() {
$this->oneSerialization("000033-002.sig");
}
public function test000034012ring_trust() {
$this->oneSerialization("000034-012.ring_trust");
}
public function test000035006public_key() {
$this->oneSerialization("000035-006.public_key");
}
public function test000036013user_id() {
$this->oneSerialization("000036-013.user_id");
}
public function test000037002sig() {
$this->oneSerialization("000037-002.sig");
}
public function test000038012ring_trust() {
$this->oneSerialization("000038-012.ring_trust");
}
public function test000039002sig() {
$this->oneSerialization("000039-002.sig");
}
public function test000040012ring_trust() {
$this->oneSerialization("000040-012.ring_trust");
}
public function test000041017attribute() {
$this->oneSerialization("000041-017.attribute");
}
public function test000042002sig() {
$this->oneSerialization("000042-002.sig");
}
public function test000043012ring_trust() {
$this->oneSerialization("000043-012.ring_trust");
}
public function test000044014public_subkey() {
$this->oneSerialization("000044-014.public_subkey");
}
public function test000045002sig() {
$this->oneSerialization("000045-002.sig");
}
public function test000046012ring_trust() {
$this->oneSerialization("000046-012.ring_trust");
}
public function test000047005secret_key() {
$this->oneSerialization("000047-005.secret_key");
}
public function test000048013user_id() {
$this->oneSerialization("000048-013.user_id");
}
public function test000049002sig() {
$this->oneSerialization("000049-002.sig");
}
public function test000050012ring_trust() {
$this->oneSerialization("000050-012.ring_trust");
}
public function test000051007secret_subkey() {
$this->oneSerialization("000051-007.secret_subkey");
}
public function test000052002sig() {
$this->oneSerialization("000052-002.sig");
}
public function test000053012ring_trust() {
$this->oneSerialization("000053-012.ring_trust");
}
public function test000054005secret_key() {
$this->oneSerialization("000054-005.secret_key");
}
public function test000055002sig() {
$this->oneSerialization("000055-002.sig");
}
public function test000056012ring_trust() {
$this->oneSerialization("000056-012.ring_trust");
}
public function test000057013user_id() {
$this->oneSerialization("000057-013.user_id");
}
public function test000058002sig() {
$this->oneSerialization("000058-002.sig");
}
public function test000059012ring_trust() {
$this->oneSerialization("000059-012.ring_trust");
}
public function test000060007secret_subkey() {
$this->oneSerialization("000060-007.secret_subkey");
}
public function test000061002sig() {
$this->oneSerialization("000061-002.sig");
}
public function test000062012ring_trust() {
$this->oneSerialization("000062-012.ring_trust");
}
public function test000063005secret_key() {
$this->oneSerialization("000063-005.secret_key");
}
public function test000064002sig() {
$this->oneSerialization("000064-002.sig");
}
public function test000065012ring_trust() {
$this->oneSerialization("000065-012.ring_trust");
}
public function test000066013user_id() {
$this->oneSerialization("000066-013.user_id");
}
public function test000067002sig() {
$this->oneSerialization("000067-002.sig");
}
public function test000068012ring_trust() {
$this->oneSerialization("000068-012.ring_trust");
}
public function test000069005secret_key() {
$this->oneSerialization("000069-005.secret_key");
}
public function test000070013user_id() {
$this->oneSerialization("000070-013.user_id");
}
public function test000071002sig() {
$this->oneSerialization("000071-002.sig");
}
public function test000072012ring_trust() {
$this->oneSerialization("000072-012.ring_trust");
}
public function test000073017attribute() {
$this->oneSerialization("000073-017.attribute");
}
public function test000074002sig() {
$this->oneSerialization("000074-002.sig");
}
public function test000075012ring_trust() {
$this->oneSerialization("000075-012.ring_trust");
}
public function test000076007secret_subkey() {
$this->oneSerialization("000076-007.secret_subkey");
}
public function test000077002sig() {
$this->oneSerialization("000077-002.sig");
}
public function test000078012ring_trust() {
$this->oneSerialization("000078-012.ring_trust");
}
public function test002182002sig() {
$this->oneSerialization("002182-002.sig");
}
public function testpubringgpg() {
$this->oneSerialization("pubring.gpg");
}
public function testsecringgpg() {
$this->oneSerialization("secring.gpg");
}
public function testcompressedsiggpg() {
$this->oneSerialization("compressedsig.gpg");
}
public function testcompressedsigzlibgpg() {
$this->oneSerialization("compressedsig-zlib.gpg");
}
public function testcompressedsigbzip2gpg() {
$this->oneSerialization("compressedsig-bzip2.gpg");
}
public function testonepass_sig() {
$this->oneSerialization("onepass_sig");
}
public function testsymmetrically_encrypted() {
$this->oneSerialization("symmetrically_encrypted");
}
public function testuncompressedopsdsagpg() {
$this->oneSerialization("uncompressed-ops-dsa.gpg");
}
public function testuncompressedopsdsasha384txtgpg() {
$this->oneSerialization("uncompressed-ops-dsa-sha384.txt.gpg");
}
public function testuncompressedopsrsagpg() {
$this->oneSerialization("uncompressed-ops-rsa.gpg");
}