PeculiarVentures / PKI.js

PKI.js is a pure JavaScript library implementing the formats that are used in PKI applications (signing, encryption, certificate requests, OCSP and TSP requests/responses). It is built on WebCrypto (Web Cryptography API) and requires no plug-ins.
http://pkijs.org
Other
1.25k stars 204 forks source link

Unable to inject Decypher KeyUsage Value into CSR #285

Closed sureshreddygovindu closed 3 years ago

sureshreddygovindu commented 3 years ago

Thank you for help!!! I'm using PKI.js to generate Certificate Signing Request(CSR). I able to generate CSR successfully but I've observed an issue with KeyUsage. I unable to inject Decipher into CSR keyUsage. I'm passing below hex values, Can you guide me right hex value for Decipher?

        const KeyUsageSupportList = {
    useDigitalSignature: 0x0080,
    useNonRepudiation: 0x0040,
    useKeyEncipher: 0x0020, //p
    useDataEncipher: 0x0010,
    useKeyAgreement: 0x0008,
    useCertificateSignature: 0x0004,
    useCRLSign: 0x0002,
    useEncipher: 0x0001,
    useDecipher: 0x8000

}
var bitArray = new ArrayBuffer(1);
var bitView = new Uint8Array(bitArray);
let keyUsageExist = false;
if (keyUsage) {
    Object.keys(keyUsage).forEach(key => {
        if (keyUsage[key]) {
            keyUsageExist = true;
            bitView[0] = bitView[0] | KeyUsageSupportList[key];
        }
    });
}
rmhrisk commented 3 years ago

Take a look at: https://github.com/PeculiarVentures/asn1-schema/tree/master/packages/csr and https://github.com/PeculiarVentures/asn1-schema/tree/master/packages/pkcs9

But if you want to do by hand: https://github.com/PeculiarVentures/csrhelp/blob/ae47240b3c3f21e94a9c59554aa5f16dd29bd148/app/assets/js/pkijs/x509_simpl.js#L5893-L5904

YuryStrozhevsky commented 3 years ago

@sureshreddygovindu Your problem is that useDecipher = 0x8000 which is NOT one byte, but two. In order to set it you need something like this:

var bitArray = new ArrayBuffer(2);
var bitView = new Uint8Array(bitArray);
...
bitView[1] = bitView[1] | KeyUsageSupportList[key];

It is just a rought explanation what you should do. Also you have incorrect KeyUsageSupportList. Here is ASN.1 description of the key usages bits from RFC5280:

      KeyUsage ::= BIT STRING {
           digitalSignature        (0),
           nonRepudiation          (1), -- recent editions of X.509 have
                                -- renamed this bit to contentCommitment
           keyEncipherment         (2),
           dataEncipherment        (3),
           keyAgreement            (4),
           keyCertSign             (5),
           cRLSign                 (6),
           encipherOnly            (7),
           decipherOnly            (8) }

So, your KeyUsageSupportList should looks like:

const KeyUsageSupportList = {
    useDigitalSignature: 0x8000,
    useNonRepudiation: 0x4000,
    useKeyEncipher: 0x2000,
    useDataEncipher: 0x1000,
    useKeyAgreement: 0x0800,
    useCertificateSignature: 0x0400,
    useCRLSign: 0x0200,
    useEncipher: 0x0100,
    useDecipher: 0x0080
}
sureshreddygovindu commented 3 years ago

Thank you for your help, @YuryStrozhevsky @rmhrisk I've fixed like this, copied key logic here, other folks may use this.


const KeyUsageSupportList = {
        useDigitalSignature: 0x0080,
        useNonRepudiation: 0x0040,
        useKeyEncipher: 0x0020, //p
        useDataEncipher: 0x0010,
        useKeyAgreement: 0x0008,
        useCertificateSignature: 0x0004,
        useCRLSign: 0x0002,
        useEncipher: 0x0001,
        useDecipher: 0x0080

    }
    var bitArray = new ArrayBuffer(2);
    var bitView = new Uint8Array(bitArray);
    let keyUsageExist = false;
    if (keyUsage) {
        Object.keys(keyUsage).forEach(key => {
            if (keyUsage[key]) {
                keyUsageExist = true;
                if (key.includes("useDecipher")) {
                    bitView[1] = bitView[1] | KeyUsageSupportList[key];
                } else {
                    bitView[0] = bitView[0] | KeyUsageSupportList[key];
                }
            }
        });
    }
    let bitKeyUsage = '';
    if (keyUsageExist) {
        bitKeyUsage = new BitString({ valueHex: bitArray });
    }
    return bitKeyUsage;
YuryStrozhevsky commented 3 years ago
useDigitalSignature: 0x0080
...
useDecipher: 0x0080