Skip to content

Commit

Permalink
U2F support (#208)
Browse files Browse the repository at this point in the history
* Create COSE from u2f public key
* add u2f key class
* rpId hash assert
  • Loading branch information
jirkasemmler authored Feb 18, 2022
1 parent 8761be6 commit 5ef9b21
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/AuthenticatorAssertionResponseValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,12 @@ class AuthenticatorAssertionResponseValidator
* @var Manager|null
*/
private $algorithmManager;

/**
* @var CounterChecker
*/
private $counterChecker;

/**
* @var LoggerInterface|null
*/
Expand Down Expand Up @@ -127,6 +129,10 @@ public function check(string $credentialId, AuthenticatorAssertionResponse $auth
}

$credentialPublicKey = $attestedCredentialData->getCredentialPublicKey();
$isU2F = U2FPublicKey::isU2FKey($credentialPublicKey);
if ($isU2F) {
$credentialPublicKey = U2FPublicKey::createCOSEKey($credentialPublicKey);
}
Assertion::notNull($credentialPublicKey, 'No public key available.');
$stream = new StringStream($credentialPublicKey);
$credentialPublicKeyStream = $this->decoder->decode($stream);
Expand Down Expand Up @@ -165,8 +171,10 @@ public function check(string $credentialId, AuthenticatorAssertionResponse $auth
$this->tokenBindingHandler->check($C->getTokenBinding(), $request);
}

$expectedRpIdHash = $isU2F ? $C->getOrigin() : $facetId;
// u2f response has full origin in rpIdHash
/** @see 7.2.11 */
$rpIdHash = hash('sha256', $facetId, true);
$rpIdHash = hash('sha256', $expectedRpIdHash, true);
Assertion::true(hash_equals($rpIdHash, $authenticatorAssertionResponse->getAuthenticatorData()->getRpIdHash()), 'rpId hash mismatch.');

/** @see 7.2.12 */
Expand Down
46 changes: 46 additions & 0 deletions src/U2FPublicKey.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Webauthn;

use CBOR\ByteStringObject;
use CBOR\MapItem;
use CBOR\MapObject;
use CBOR\NegativeIntegerObject;
use CBOR\UnsignedIntegerObject;

class U2FPublicKey
{
public static function isU2FKey($publicKey): bool
{
return $publicKey[0] === "\x04";
}

public static function createCOSEKey($publicKey): string
{

$mapObject = new MapObject([
1 => MapItem::create(
new UnsignedIntegerObject(1, null),
new UnsignedIntegerObject(2, null)
),
3 => MapItem::create(
new UnsignedIntegerObject(3, null),
new NegativeIntegerObject(6, null)
),
-1 => MapItem::create(
new NegativeIntegerObject(0, null),
new UnsignedIntegerObject(1, null)
),
-2 => MapItem::create(
new NegativeIntegerObject(1, null),
new ByteStringObject(substr($publicKey, 1, 32))
),
-3 => MapItem::create(
new NegativeIntegerObject(2, null),
new ByteStringObject(substr($publicKey, 33))
),
]);

return $mapObject->__toString();
}
}

0 comments on commit 5ef9b21

Please sign in to comment.