Giter Club home page Giter Club logo

cose-lib's Introduction

COSE Support for PHP

CBOR Object Signing and Encryption (COSE) Support for PHP is a PHP library that will help you to perform cypher operations using Cose Keys.

Build Status

Latest Stable Version Total Downloads Latest Unstable Version License

OpenSSF Scorecard

Installation

Install the library with Composer: composer require web-auth/cose-lib.

How to use

To be written

Support

I bring solutions to your problems and answer your questions.

If you really love that project, and the work I have done or if you want I prioritize your issues, then you can help me out for a couple of 🍻 or more!

Become a sponsor

Or

Become a Patreon

Contributing

Requests for new features, bug fixed and all other ideas to make this library useful are welcome. Please follow these best practices.

If you discover a security vulnerability within the project, please don't use the bug tracker and don't publish it publicly. Instead, all security issues must be sent to security [at] spomky-labs.com.

Licence

This software is release under MIT licence.

cose-lib's People

Contributors

dependabot[bot] avatar fnpen avatar github-actions[bot] avatar spomky avatar szepeviktor avatar timwolla avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

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.