-
-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Linebreaks in clearsigned message seem to break signature #136
Comments
@singpolyma I wanted to follow up on this issue to see if there might be any updates or if there's anything I can do to help move it forward. Thanks |
Both security.txt as the PGP cleartext signature use the Internet standard newline
Source: RFC 4880 - OpenPGP Message Format - 7.1. Dash-Escaped Text. So it's to be expected if openpgp-php is cleartext unaware (only It took me a while to get your sample working, because of another
and
It results in this modified example that works for me (which I placed in the example directory of openpgp-php-0.6.0): <?php
use phpseclib3\Crypt\RSA;
use phpseclib3\Crypt\RSA\Formats\Keys\PKCS1;
include_once dirname(__FILE__).'/../vendor/autoload.php';
require_once dirname(__FILE__).'/../lib/openpgp.php';
require_once dirname(__FILE__).'/../lib/openpgp_crypt_rsa.php';
$name = "dummy";
$email = "security@example.org";
$passphrase = "high-entropy-passphrase";
$key_length = 2048;
// Generate a key pair
$privateKey = RSA::createKey($key_length);
$privateKeyComponents = PKCS1::load($privateKey->toString('PKCS1'));
$secretKeyPacket = new OpenPGP_SecretKeyPacket(array(
'n' => $privateKeyComponents["modulus"]->toBytes(),
'e' => $privateKeyComponents["publicExponent"]->toBytes(),
'd' => $privateKeyComponents["privateExponent"]->toBytes(),
'p' => $privateKeyComponents["primes"][1]->toBytes(),
'q' => $privateKeyComponents["primes"][2]->toBytes(),
'u' => $privateKeyComponents["coefficients"][2]->toBytes()
));
// Assemble packets for the private key
$packets = array($secretKeyPacket);
$wkey = new OpenPGP_Crypt_RSA($secretKeyPacket);
$fingerprint = $wkey->key()->fingerprint;
$key = $wkey->private_key();
$key = $key->withHash('sha256');
$keyid = substr($fingerprint, -16);
// Add a user ID packet
$uid = new OpenPGP_UserIDPacket("$name <$email>");
$packets[] = $uid;
// Add a signature packet to certify the binding between the user ID and the key
$sig = new OpenPGP_SignaturePacket(new OpenPGP_Message(array($secretKeyPacket, $uid)), 'RSA', 'SHA256');
$sig->signature_type = 0x13;
$sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_KeyFlagsPacket(array(0x01 | 0x02 | 0x04)); // Certify + sign + encrypt bits
$sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_IssuerPacket($keyid);
$m = $wkey->sign_key_userid(array($secretKeyPacket, $uid, $sig));
// Append the signature to the private key packets
$packets[] = $m->packets[2];
// Assemble packets for the public key
$publicPackets = array(new OpenPGP_PublicKeyPacket($secretKeyPacket));
$publicPackets[] = $uid;
$publicPackets[] = $sig;
// Encrypt the private key with a passphrase
$encryptedSecretKeyPacket = OpenPGP_Crypt_Symmetric::encryptSecretKey($passphrase, $secretKeyPacket);
// Assemble the private key message
$privateMessage = new OpenPGP_Message($packets);
$privateMessage[0] = $encryptedSecretKeyPacket;
// Enarmor the private key message
$privateEnarmorKey = OpenPGP::enarmor($privateMessage->to_bytes(), "PGP PRIVATE KEY BLOCK");
// Assemble the public key message
$publicMessage = new OpenPGP_Message($publicPackets);
// Enarmor the public key message
$publicEnarmorKey = OpenPGP::enarmor($publicMessage->to_bytes(), "PGP PUBLIC KEY BLOCK");
$string = "Contact: mailto:$email\r\nExpires: 2025-04-29T00:00:00Z\r\nPreferred-Languages: en\r\nEncryption: https://www.example.org/publickey.txt\r\nCanonical: https://www.example.org/.well-known/security.txt";
$m = $wkey->sign($string);
/* Generate clearsigned data */
$packets = $m->signatures()[0];
$file_contents = "-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: SHA256\r\n\r\n";
// Output normalised data. You could convert line endings here
// or add trailing whitespace (spaces and tabs) to lines without breaking the signature
$file_contents .= preg_replace("/^-/", "- -", $packets[0]->data) . "\r\n";
$file_contents .= OpenPGP::enarmor($packets[1][0]->to_bytes(), "PGP SIGNATURE");
$parsed_pubkey = OpenPGP_Message::parse($publicEnarmorKey);
/* Parse signed message from file named "t" */
$m = OpenPGP_Message::parse($file_contents);
/* Create a verifier for the key */
$verify = new OpenPGP_Crypt_RSA($parsed_pubkey);
// We verify
$verified = (bool)$verify->verify($m);
echo var_export(array(
'signed_message' => $file_contents,
'public_key' => $publicEnarmorKey,
'private_key' => $privateEnarmorKey,
'verified' => $verified
)); Which will result in a signed security.txt:
with the publickey.txt:
which validates in gpg: $ gpg --no-default-keyring --keyring tmp.gpg --import publickey.txt && gpg --keyring tmp.gpg --verify security.txt
gpg: key 1CDC7AEEC605EB73: public key "dummy <security@example.org>" imported
gpg: Total number processed: 1
gpg: imported: 1
gpg: Signature made Tue 11 Jun 2024 10:32:55 PM CEST
gpg: using RSA key 1CDC7AEEC605EB73
gpg: Good signature from "dummy <security@example.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 4BA6 5740 4364 D93F 1F87 3681 1CDC 7AEE C605 EB73 Also https://pgptool.org/ validates. |
@bwbroersma I totally missed the |
I'm trying to clearsign a message, which works fine until I add \n linebreaks into the message. After that the signature can't be verified anymore.
Most of my function is simply taken from the keygen, clearsign and verify examples. My goal is generate and return new private and public keys and clearsign a file with a valid signature.
Contents from file $SecurityTxtAdmin->get_securitytxt_file_contents();
After clearsign
The above signature can be verified correctly with a tool such as GPG Suite or https://pgptool.org/. However if I enter any \n linebreaks into this file, it will break the signature and these tools give a bad result. Linebreaks are essential for my implementation. The public key for this file is;
After introducing linebreaks:
The above signature is not valid according to the earlier mentioned GPG tools. The public key for this file is;
Please let me know if you need more information.
The text was updated successfully, but these errors were encountered: