Coder Social home page Coder Social logo

cose-lib's Issues

Check of key type and curve assume value is int

Version(s) affected

4.2.0

Description

When you check fields 1 and -1 of an OKP key, you assume the value is an integer, or following rfc9053, it can also be a text string. So if I have a registered key and the cbor map contains tstr as values and not integer, verify throw an exception.

Linked to issue 448 of web-auth/webauthn-framework (web-auth/webauthn-framework#448)

How to reproduce

With this binary key:

0xA401634F4B50032720674564323535313921582098C91448E657A3366C3C04551DAFD92A8BB2BA35138B4ACB94CA1E79D2627BAE
{1: "OKP", 3: -8, -1: "Ed25519", -2: h'98C91448E657A3366C3C04551DAFD92A8BB2BA35138B4ACB94CA1E79D2627BAE'}

Currently the lib throw an exception but the key is valid.

Possible Solution

No response

Additional Context

No response

COSEToPEMConverter that’s compatible with PHP 5.6

Description

I’ve been looking for a COSEToPEMConverter that’s compatible with PHP 5.6, because the minimum requirement for web-auth/cose-lib is PHP 7.0. It’s been a desperate search, taking up 2 weeks of my time. If anyone else finds this library and realizes their version is also PHP 5.6, you can try it out, giving you a glimmer of hope. This is just the most basic support, I’ve only tested it with Windows Hello, I can’t afford to buy a physical key because it’s too expensive. So, I haven’t tried ES256, but RSA works fine.

Example

class COSEToPEMConverter_v2 {
  
    public function extractCoseKeyAndAlg($attestationObject) {

	$attestationObject_decode = base64url_decode($attestationObject);
        $decoder = new CBOREncoder();
        $decoded = $decoder->decode($attestationObject_decode);

        // Extract attStmt from decoded structure
        $attStmt = $decoded['attStmt'];
        $alg = $attStmt['alg'];

        // Extract authData from decoded structure
        $authData = $decoded['authData']->get_byte_string();
        $coseKey = $this->extractCoseKeyFromAuthData($authData);

        return ['coseKey'=>$coseKey, 'alg'=> $alg];
    }

    private function extractCoseKeyFromAuthData($authData) {
        $offset = 37; // RP ID Hash (32) + Flags (1) + Sign Count (4)
        $aaguid = substr($authData, $offset, 16);
        $offset += 16;
        $credentialIdLength = unpack('n', substr($authData, $offset, 2))[1];
        $offset += 2;
        $credentialId = substr($authData, $offset, $credentialIdLength);
        $offset += $credentialIdLength;

        // The remaining data is the COSE Key
        $coseKey = substr($authData, $offset);

        return $coseKey;
    }

    public function createPemFromCoseKey($coseKey, $alg) {
        $decoder = new CBOREncoder();
        $coseData = $decoder->decode($coseKey);

        // Debug: Print the COSE data
        //var_dump($coseData);

        if ($alg == -257) { // RS256 algorithm
            $n = $coseData[-1]->get_byte_string();
            $e = $coseData[-2]->get_byte_string();

            // Debug: Print the key parameters
           // var_dump($n, $e);

            $asn1 = $this->buildRsaPublicKey($n, $e);

            $pem = "-----BEGIN PUBLIC KEY-----\n";
            $pem .= chunk_split(base64_encode($asn1), 64, "\n");
            $pem .= "-----END PUBLIC KEY-----\n";

            return $pem;
        } elseif ($alg == -7) { // ES256 (ECDSA) algorithm
            $x = $coseData[-2]->get_byte_string();
            $y = $coseData[-3]->get_byte_string();

            // Debug: Print the key parameters
            //var_dump($x, $y);

            $asn1 = $this->buildEcdsaPublicKey($x, $y);

            $pem = "-----BEGIN PUBLIC KEY-----\n";
            $pem .= chunk_split(base64_encode($asn1), 64, "\n");
            $pem .= "-----END PUBLIC KEY-----\n";

            return $pem;
        }  else {
            throw new Exception('Unsupported key type or algorithm');
        }
    }

    private function buildRsaPublicKey($n, $e) {
        // Ensure the length of n and e are correctly encoded in ASN.1 format
        $n = ltrim($n, "\x00"); // Remove leading null bytes
        $e = ltrim($e, "\x00"); // Remove leading null bytes

        // ASN.1 structure
        $asn1_n = "\x02" . $this->lengthBytes(strlen($n)) . $n;
        $asn1_e = "\x02" . $this->lengthBytes(strlen($e)) . $e;
        $asn1_seq = "\x30" . $this->lengthBytes(strlen($asn1_n) + strlen($asn1_e)) . $asn1_n . $asn1_e;

        $asn1_bitstring = "\x03" . $this->lengthBytes(strlen($asn1_seq) + 1) . "\x00" . $asn1_seq;
        $asn1_algo = "\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00";
        $asn1_pubkey = "\x30" . $this->lengthBytes(strlen($asn1_algo) + strlen($asn1_bitstring)) . $asn1_algo . $asn1_bitstring;

        return $asn1_pubkey;
    }

    private function buildEcdsaPublicKey($x, $y) {
        // Ensure the length of x and y are correctly encoded in ASN.1 format
        $x = ltrim($x, "\x00"); // Remove leading null bytes
        $y = ltrim($y, "\x00"); // Remove leading null bytes

        $ecPublicKey = "\x04" . $x . $y;

        // ASN.1 structure
        $asn1_bitstring = "\x03" . $this->lengthBytes(strlen($ecPublicKey) + 1) . "\x00" . $ecPublicKey;
        $asn1_algo = "\x30\x13\x06\x07\x2A\x86\x48\xCE\x3D\x02\x01\x06\x08\x2A\x86\x48\xCE\x3D\x03\x01\x07";
        $asn1_pubkey = "\x30" . $this->lengthBytes(strlen($asn1_algo) + strlen($asn1_bitstring)) . $asn1_algo . $asn1_bitstring;

        return $asn1_pubkey;
    }

    private function lengthBytes($length) {
        if ($length < 128) {
            return chr($length);
        } elseif ($length < 256) {
            return "\x81" . chr($length);
        } else {
            return "\x82" . pack('n', $length);
        }
    }


}
function base64url_encode($data) {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

function base64url_decode($data) {
    return base64_decode(strtr($data, '-_', '+/'));
}

使用方法:

         // Decode the CBOR object
	// composer require 2tvenom/cborencode   安装命令
	$converter = new COSEToPEMConverter_v2();
	$CoseKeyAndAlg = $converter->extractCoseKeyAndAlg($attestationObject);
	$pemKey = $converter->createPemFromCoseKey($CoseKeyAndAlg['coseKey'], $CoseKeyAndAlg['alg']);
	// 创建一个 OpenSSL 公钥资源
	$publicKey = openssl_pkey_get_public($pemKey);

备注 :

"The object passed from the front end to the back end depends on the encoding you use. The navigator.credentials.create function returns a credential, where attestationObject is base64url(credential.response.attestationObject).

Because I'm using the following function to encode:

function base64url(buffer) {
	return btoa(String.fromCharCode.apply(null, new Uint8Array(buffer)))
		.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

Wishing good luck to those who come after, the fallen 5.6.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.