forked from GNUsocial/gnu-social
Magicsig::generate is now static
This also fixes a problem with "initial salmon slap", which was a problem for newly registered accounts which would have their first salmon slap fail to distribute since there was a problem with Magicsig keys. Apparently we have to re-read them with importKeys so the Crypt_RSA objects publicKey and privateKey match later instances of them. I think it may have been that generate() doesn't specify a signatureMode, but I leave experimentation of that to the future.
This commit is contained in:
parent
537dff7987
commit
0bc122ff58
@ -1344,9 +1344,7 @@ class OStatusPlugin extends Plugin
|
|||||||
// Get this profile's keypair
|
// Get this profile's keypair
|
||||||
$magicsig = Magicsig::getKV('user_id', $target->id);
|
$magicsig = Magicsig::getKV('user_id', $target->id);
|
||||||
if (!$magicsig instanceof Magicsig && $target->isLocal()) {
|
if (!$magicsig instanceof Magicsig && $target->isLocal()) {
|
||||||
// No keypair yet, let's generate one. Only for local users.
|
$magicsig = Magicsig::generate($target->getUser());
|
||||||
$magicsig = new Magicsig();
|
|
||||||
$magicsig->generate($target->getUser());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($magicsig instanceof Magicsig) {
|
if ($magicsig instanceof Magicsig) {
|
||||||
|
@ -132,7 +132,7 @@ class Magicsig extends Managed_DataObject
|
|||||||
*/
|
*/
|
||||||
function insert()
|
function insert()
|
||||||
{
|
{
|
||||||
$this->keypair = $this->toString();
|
$this->keypair = $this->toString(true);
|
||||||
|
|
||||||
return parent::insert();
|
return parent::insert();
|
||||||
}
|
}
|
||||||
@ -145,20 +145,25 @@ class Magicsig extends Managed_DataObject
|
|||||||
*
|
*
|
||||||
* @param User $user the local user (since we don't have remote private keys)
|
* @param User $user the local user (since we don't have remote private keys)
|
||||||
*/
|
*/
|
||||||
public function generate(User $user, $bits=1024)
|
public static function generate(User $user, $bits=1024, $alg='RSA-SHA256')
|
||||||
{
|
{
|
||||||
|
$magicsig = new Magicsig($alg);
|
||||||
|
$magicsig->user_id = $user->id;
|
||||||
|
|
||||||
$rsa = new Crypt_RSA();
|
$rsa = new Crypt_RSA();
|
||||||
|
|
||||||
$keypair = $rsa->createKey($bits);
|
$keypair = $rsa->createKey($bits);
|
||||||
|
|
||||||
$this->privateKey = new Crypt_RSA();
|
$magicsig->privateKey = new Crypt_RSA();
|
||||||
$this->privateKey->loadKey($keypair['privatekey']);
|
$magicsig->privateKey->loadKey($keypair['privatekey']);
|
||||||
|
|
||||||
$this->publicKey = new Crypt_RSA();
|
$magicsig->publicKey = new Crypt_RSA();
|
||||||
$this->publicKey->loadKey($keypair['publickey']);
|
$magicsig->publicKey->loadKey($keypair['publickey']);
|
||||||
|
|
||||||
$this->user_id = $user->id;
|
$magicsig->insert(); // will do $this->keypair = $this->toString(true);
|
||||||
$this->insert();
|
$magicsig->importKeys(); // seems it's necessary to re-read keys from text keypair
|
||||||
|
|
||||||
|
return $magicsig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -172,7 +177,7 @@ class Magicsig extends Managed_DataObject
|
|||||||
$mod = Magicsig::base64_url_encode($this->publicKey->modulus->toBytes());
|
$mod = Magicsig::base64_url_encode($this->publicKey->modulus->toBytes());
|
||||||
$exp = Magicsig::base64_url_encode($this->publicKey->exponent->toBytes());
|
$exp = Magicsig::base64_url_encode($this->publicKey->exponent->toBytes());
|
||||||
$private_exp = '';
|
$private_exp = '';
|
||||||
if ($full_pair && $this->privateKey->exponent->toBytes()) {
|
if ($full_pair && $this->privateKey instanceof Crypt_RSA && $this->privateKey->exponent->toBytes()) {
|
||||||
$private_exp = '.' . Magicsig::base64_url_encode($this->privateKey->exponent->toBytes());
|
$private_exp = '.' . Magicsig::base64_url_encode($this->privateKey->exponent->toBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,21 +153,23 @@ class MagicEnvelope
|
|||||||
* @param <type> $text
|
* @param <type> $text
|
||||||
* @param <type> $mimetype
|
* @param <type> $mimetype
|
||||||
* @param Magicsig $magicsig Magicsig with private key available.
|
* @param Magicsig $magicsig Magicsig with private key available.
|
||||||
|
*
|
||||||
* @return MagicEnvelope object with all properties set
|
* @return MagicEnvelope object with all properties set
|
||||||
|
*
|
||||||
|
* @throws Exception of various kinds on signing failure
|
||||||
*/
|
*/
|
||||||
public static function signMessage($text, $mimetype, Magicsig $magicsig)
|
public function signMessage($text, $mimetype, Magicsig $magicsig)
|
||||||
{
|
{
|
||||||
$magic_env = new MagicEnvelope();
|
assert($magicsig->privateKey instanceof Crypt_RSA);
|
||||||
|
|
||||||
// Prepare text and metadata for signing
|
// Prepare text and metadata for signing
|
||||||
$magic_env->data = Magicsig::base64_url_encode($text);
|
$this->data = Magicsig::base64_url_encode($text);
|
||||||
$magic_env->data_type = $mimetype;
|
$this->data_type = $mimetype;
|
||||||
$magic_env->encoding = self::ENCODING;
|
$this->encoding = self::ENCODING;
|
||||||
$magic_env->alg = $magicsig->getName();
|
$this->alg = $magicsig->getName();
|
||||||
// Get the actual signature
|
|
||||||
$magic_env->sig = $magicsig->sign($magic_env->signingText());
|
|
||||||
|
|
||||||
return $magic_env;
|
// Get the actual signature
|
||||||
|
$this->sig = $magicsig->sign($this->signingText());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -182,7 +184,7 @@ class MagicEnvelope
|
|||||||
$xs->element('me:data', array('type' => $this->data_type), $this->data);
|
$xs->element('me:data', array('type' => $this->data_type), $this->data);
|
||||||
$xs->element('me:encoding', null, $this->encoding);
|
$xs->element('me:encoding', null, $this->encoding);
|
||||||
$xs->element('me:alg', null, $this->alg);
|
$xs->element('me:alg', null, $this->alg);
|
||||||
$xs->element('me:sig', null, $this->sig);
|
$xs->element('me:sig', null, $this->getSignature());
|
||||||
$xs->elementEnd('me:env');
|
$xs->elementEnd('me:env');
|
||||||
|
|
||||||
$string = $xs->getString();
|
$string = $xs->getString();
|
||||||
@ -220,7 +222,7 @@ class MagicEnvelope
|
|||||||
$prov->appendChild($enc);
|
$prov->appendChild($enc);
|
||||||
$alg = $dom->createElementNS(self::NS, 'me:alg', $this->alg);
|
$alg = $dom->createElementNS(self::NS, 'me:alg', $this->alg);
|
||||||
$prov->appendChild($alg);
|
$prov->appendChild($alg);
|
||||||
$sig = $dom->createElementNS(self::NS, 'me:sig', $this->sig);
|
$sig = $dom->createElementNS(self::NS, 'me:sig', $this->getSignature());
|
||||||
$prov->appendChild($sig);
|
$prov->appendChild($sig);
|
||||||
|
|
||||||
$dom->documentElement->appendChild($prov);
|
$dom->documentElement->appendChild($prov);
|
||||||
@ -231,6 +233,11 @@ class MagicEnvelope
|
|||||||
return $dom;
|
return $dom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSignature()
|
||||||
|
{
|
||||||
|
return $this->sig;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the author URI referenced in the payload Atom entry.
|
* Find the author URI referenced in the payload Atom entry.
|
||||||
*
|
*
|
||||||
@ -280,7 +287,7 @@ class MagicEnvelope
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $magicsig->verify($this->signingText(), $this->sig);
|
return $magicsig->verify($this->signingText(), $this->getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -326,24 +333,22 @@ class MagicEnvelope
|
|||||||
* @param string $text XML fragment to sign, assumed to be Atom
|
* @param string $text XML fragment to sign, assumed to be Atom
|
||||||
* @param User $user User who cryptographically signs $text
|
* @param User $user User who cryptographically signs $text
|
||||||
*
|
*
|
||||||
* @return string XML string representation of magic envelope
|
* @return MagicEnvelope object complete with signature
|
||||||
*
|
*
|
||||||
* @throws Exception on bad profile input or key generation problems
|
* @throws Exception on bad profile input or key generation problems
|
||||||
* @fixme if signing fails, this seems to return the original text without warning. Is there a reason for this?
|
|
||||||
*/
|
*/
|
||||||
public static function signAsUser($text, User $user)
|
public static function signAsUser($text, User $user)
|
||||||
{
|
{
|
||||||
// Find already stored key
|
// Find already stored key
|
||||||
$magicsig = Magicsig::getKV('user_id', $user->id);
|
$magicsig = Magicsig::getKV('user_id', $user->id);
|
||||||
if (!$magicsig instanceof Magicsig) {
|
if (!$magicsig instanceof Magicsig) {
|
||||||
// No keypair yet, let's generate one.
|
$magicsig = Magicsig::generate($user);
|
||||||
$magicsig = new Magicsig();
|
|
||||||
$magicsig->generate($user);
|
|
||||||
}
|
}
|
||||||
|
assert($magicsig instanceof Magicsig);
|
||||||
|
assert($magicsig->privateKey instanceof Crypt_RSA);
|
||||||
|
|
||||||
$magic_env = self::signMessage($text, 'application/atom+xml', $magicsig);
|
$magic_env = new MagicEnvelope();
|
||||||
|
$magic_env->signMessage($text, 'application/atom+xml', $magicsig);
|
||||||
assert($magic_env instanceof MagicEnvelope);
|
|
||||||
|
|
||||||
return $magic_env;
|
return $magic_env;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user