public function sign($message, $hash_alg)
{
$hash = new Crypt\Hash($hash_alg);
$zero = new BigInteger();
$g = new BigInteger($this->_key->key['g'], 256);
$p = new BigInteger($this->_key->key['p'], 256);
$q = new BigInteger($this->_key->key['q'], 256);
$x = new BigInteger($this->_key->key['x'], 256);
$bigint_hash = new BigInteger($hash->hash($message), 256);
while (true) {
$k = self::randomNumber($q);
$r_base = $g->modPow($k, $p)->divide($q);
$r = $r_base[1];
if ($r->compare($zero) == 0) {
continue;
}
// compute H(m) + (x*r)
$x_mul_r_base = $x->multiply($r)->divide($q);
$x_mul_r = $x_mul_r_base[1];
$bh = clone $bigint_hash;
$message_dep_base = $bh->add($x_mul_r)->divide($q);
$message_dep = $message_dep_base[1];
// compute s
$k_modInv = $k->modInverse($q);
$k_modInv_mul = $k_modInv->multiply($message_dep);
$s_base = $k_modInv_mul->divide($q);
$s = $s_base[1];
if ($s->compare($zero) != 0) {
// r and s are non-zero, we can continue
break;
}
}
return array('r' => $r->toBytes(), 's' => $s->toBytes());
}
/** */ public function sign($text, $key, $mode, $opts = array()) { $rsa = new OpenPGP_Crypt_RSA($key->message); $pkey = $rsa->key(); $text = $this->_getMessageOb($text)->packets[0]; switch ($pkey->algorithm) { case 1: case 2: case 3: // RSA $hash = $opts['sign_hash'] ?: 'SHA256'; $result = $rsa->sign($text, $hash); break; case 17: // DSA; use SHA1 by default, since that is what DSA/DSS was // designed for. $hash = $opts['sign_hash'] ?: 'SHA1'; $sig = new OpenPGP_SignaturePacket($text, 'DSA', $hash); $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_IssuerPacket(substr($pkey->fingerprint, -16)); $dsa = new Horde_Pgp_Crypt_DSA($pkey); $sig->sign_data(array('DSA' => array($hash => function ($data) use($dsa, $hash) { return $dsa->sign($data, $hash); }))); $result = new OpenPGP_Message(array($sig, $text)); break; } switch ($mode) { case 'clear': $sm = new Horde_Pgp_Element_SignedMessage(new OpenPGP_Message(array($result[1], $result[0]))); $sm->headers['Hash'] = $hash; return $sm; case 'detach': foreach ($result as $val) { if ($val instanceof OpenPGP_SignaturePacket) { return new Horde_Pgp_Element_Signature(new OpenPGP_Message(array($val))); } } break; case 'message': return new Horde_Pgp_Element_Message($this->_compressMessageOb($result, $opts['compress'])); } }