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

PKCS12 using ECC KeyTypes and ECC Certificate Authority #262

Closed sureshreddygovindu closed 4 years ago

sureshreddygovindu commented 4 years ago

Thanks for your work. I would like to create PKCS12 cert using (private key, Certificate and Chain) which is belongs ECC(ECCPRIME256V1) keytype and Certificate Authority is ECCC_ICA. I unable to find proper instructions to generate pkcs12 using above keytypes, can you guide me please?

sureshreddygovindu commented 4 years ago

any update on it?

YuryStrozhevsky commented 4 years ago

@sureshreddygovindu PKI.js by default works with WebCrypto API algorithms only. But there is a "fine-tunning" mechanism calling "crypto engine". Here is the example where you could see both PKCS#12 usage and specific crypto engine realization.

sureshreddygovindu commented 4 years ago

Thanks @YuryStrozhevsky I'm trying to use pkcs12 example, It is working for Private Key and Certificate which are given in the example, when I'm passing RSA Private key, I see below exception at this line let asn1 = asn1js.fromBER(keyBuffer);

Object's schema was not verified against input data for PrivateKeyInfo

rmhrisk commented 4 years ago

@sureshreddygovindu without:

  1. example of code you are using
  2. example input you are using with the code

there is really not much we can do to debug a message like this.

The error basically says you gave us something other than PrivateKeyInfo, I would start there.

sureshreddygovindu commented 4 years ago

@rmhrisk Thanks for reply.


const atob = require('atob');
const asn1js = require('asn1js');
const fs = require('fs');
const pkijs = require('pkijs');
const pvutils = require('pvutils')
const save = require('save-file')

const { getCrypto, getAlgorithmParameters, getRandomValues, setEnginegetName, dob, setEngine } = require('pkijs');
const { stringToArrayBuffer, arrayBufferToString, fromBase64, toBase64 } = require('pvutils')
const { SafeBag, PFX, PrivateKeyInfo, AuthenticatedSafe, SafeContents, CertBag, Certificate } = require('pkijs');

//import { getCrypto, getAlgorithmParameters, getRandomValues, setEngine } from "../../src/common";

//const Certificate = pkijs.Certificate

let certificateBuffer = new ArrayBuffer(0);

function init() {
    let pemFile = fs.readFileSync('key-RSA-4096.pem', 'utf8');
    certificateBuffer = convertPemToBinary(pemFile);

    let asn1 = asn1js.fromBER(certificateBuffer);
    if (asn1.offset === (-1)) {
        console.log("Can not parse binary data");
    }

    const certificate = new PrivateKeyInfo({ schema: asn1.result });
    console.log(certificate);
    // certDownload("test");
  //  printCertificate(certificateBuffer);
}

function convertPemToBinary(pem) {
    var lines = pem.split('\n');
    var encoded = '';
    for (var i = 0; i < lines.length; i++) {
        if (lines[i].trim().length > 0 &&
            lines[i].indexOf('-BEGIN RSA PRIVATE KEY-') < 0 &&
            lines[i].indexOf('-BEGIN RSA PUBLIC KEY-') < 0 &&
            lines[i].indexOf('-BEGIN PUBLIC KEY-') < 0 &&
            lines[i].indexOf('-BEGIN CERTIFICATE-') < 0 &&
            lines[i].indexOf('-BEGIN PRIVATE KEY-') < 0 &&
            lines[i].indexOf('-END PRIVATE KEY-') < 0 &&
            lines[i].indexOf('-END CERTIFICATE-') < 0 &&
            lines[i].indexOf('-END PUBLIC KEY-') < 0 &&
            lines[i].indexOf('-END RSA PRIVATE KEY-') < 0 &&
            lines[i].indexOf('-END RSA PUBLIC KEY-') < 0) {
            encoded += lines[i].trim();
        }
    }

    return base64StringToArrayBuffer(encoded);
}

function base64StringToArrayBuffer(b64str) {
    console.log(b64str + "^^^^^^^^^^")
    let byteStr = atob(b64str);

    let bytes = new Uint8Array(byteStr.length);
    for (let i = 0; i < byteStr.length; i++) {
        bytes[i] = byteStr.charCodeAt(i);
    }
    //var raw = new Buffer(CertPEM, 'base64').toString('binary');

    return bytes.buffer;
}```
sureshreddygovindu commented 4 years ago

Can you put this private key key-RSA-4096.pem


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
-----END RSA PRIVATE KEY-----```
sureshreddygovindu commented 4 years ago

@rmhrisk If you run above code, you can see the exception Object's schema was not verified against input data for PrivateKeyInfo

YuryStrozhevsky commented 4 years ago

@sureshreddygovindu You are trying to pass ASN.1 data from RSAPrivateKey and validate it against PrivateKeyInfo class. Just use correct:

const asn1 = asn1js.fromBER(stringToArrayBuffer(fromBase64(b64)));
const privateKey = new pkijs.RSAPrivateKey({ schema: asn1.result });
sureshreddygovindu commented 4 years ago

@YuryStrozhevsky Thank you for quick response, When I use RSAPrivateKey/ECPrivateKey while generation of PKCS12, I see exceptions.

  1. When I use default PrivateKey/Certificate given in the example, it's working fine, here, they are using PrivateKeyInfo class. https://pkijs.org/examples/PKCS12SimpleExample.html

below is my code snippet.


    function passwordPrivacyInternal(password) {
        console.log("**************************")
        //region Initial variables
        var sequence = Promise.resolve();

        var passwordConverted = stringToArrayBuffer(password);
        //endregion

        certificateBASE64 = "MIICljCCAjygAwIBAgIUeSwhSH6YSv4LMGWCh1DLd8n7oIAwCgYIKoZIzj0EAwIwNzE1MDMGA1UEAwwsUUEgT05MWSAtIFhmaW5pdHkgU3Vic2NyaWJlciBJc3N1aW5nIEVDQyBJQ0EwHhcNMjAwNDIwMjAyNTU5WhcNMjAwNDIyMjIyNTU5WjCBpzEVMBMGA1UEBwwMUGhpbGFkZWxwaGlhMQswCQYDVQQIDAJQQTELMAkGA1UEBgwCVVMxHDAaBgNVBAMME0VDQ2RlbW8uY29tY2FzdC5jb20xEDAOBgNVBAsMB1hmaW5pdHkxEDAOBgNVBAoMB0NvbWNhc3QxMjAwBgoJkiaJk/IsZAEBDCIxR1pLUjllc1Z1aVNjc2RURGZpdkNZeHVROWY3SlZyRjVzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6dDBAXOEbl0bq+kR3JAex4SKz8gVcMCopLdxaeYFdAPOMTdifQuB1+lSQ6Lyl3Vq8zFrKwW6hU9RQ5gS1tjb66OBtDCBsTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFMlnXX1YRTAkKnq/IyKK/IBMdkYjMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYWaHR0cDovL29jc3AtcWEueHBraS5pbzAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwHQYDVR0OBBYEFDzZMoW2HJbey4nySp+vDGyreDRGMA4GA1UdDwEB/wQEAwIFoDAKBggqhkjOPQQDAgNIADBFAiEA/hUDUgBJXv6AqmfP2AznmjRq9yyig6ok+CejyvinEqICIGD16qHDv131YVRjPcCe5w/P2hgGkbdeUMhj2Gf4f5A8";

        privateKeyBASE64 = "MHcCAQEEIHlY0FBpEKL+EVEdkDk9x0OxTEO8HJrPxH2ALoB5+xDIoAoGCCqGSM49AwEHoUQDQgAE6dDBAXOEbl0bq+kR3JAex4SKz8gVcMCopLdxaeYFdAPOMTdifQuB1+lSQ6Lyl3Vq8zFrKwW6hU9RQ5gS1tjb6w==";

        //region Create simplified structires for certificate and private key
        var asn1 = fromBER(stringToArrayBuffer(fromBase64(certificateBASE64)));
        var certSimpl = new Certificate({ schema: asn1.result });

        asn1 = fromBER(stringToArrayBuffer(fromBase64(privateKeyBASE64)));
        var pkcs8Simpl = new ECPrivateKey({ schema: asn1.result });
        //endregion

        console.log(pkcs8Simpl)
        //region Put initial values for PKCS#12 structures
        //region Put initial values for PKCS#12 structures
        var pkcs12 = new PFX({
            parsedValue: {
                integrityMode: 0, // Password-Based Integrity Mode
                authenticatedSafe: new AuthenticatedSafe({
                    parsedValue: {
                        safeContents: [{
                            privacyMode: 1, // Password-Based Privacy Protection Mode
                            value: new SafeContents({
                                safeBags: [new SafeBag({
                                    bagId: "1.2.840.113549.1.12.10.1.1",
                                    bagValue: pkcs8Simpl
                                }), new SafeBag({
                                    bagId: "1.2.840.113549.1.12.10.1.3",
                                    bagValue: new CertBag({
                                        parsedValue: certSimpl
                                    })
                                })]
                            })
                        }]
                    }
                })
            }
        });
        //endregion

        //region Encode internal values for all "SafeContents" firts (create all "Privacy Protection" envelopes)
        sequence = sequence.then(() => pkcs12.parsedValue.authenticatedSafe.makeInternalValues({
            safeContents: [{
                password: passwordConverted,
                contentEncryptionAlgorithm: {
                    name: "AES-CBC",
                    length: 128
                },
                hmacHashAlgorithm: "SHA-256",
                iterationCount: 2048
            }]
        }));
        //endregion

        //region Encode internal values for "Integrity Protection" envelope
        sequence = sequence.then(() => pkcs12.makeInternalValues({
            password: passwordConverted,
            iterations: 100000,
            pbkdf2HashAlgorithm: "SHA-256", // Least two parameters are equal because at the moment it is not clear how to use PBMAC1 schema with PKCS#12 integrity protection
            hmacHashAlgorithm: "SHA-256"
        }));
        //endregion

        //region Save encoded data
        sequence = sequence.then(() => pkcs12.toSchema().toBER(false));
        //endregion

        return sequence;
    }```
sureshreddygovindu commented 4 years ago

Can you please help me why I unable generate PKCS12 when I use ECPrivateKey type. If I use PrivateKeyInfo class, mentioned exception Object's schema was not verified against input data for PrivateKeyInfo

YuryStrozhevsky commented 4 years ago

@sureshreddygovindu I do not have a time (and will, frankly speaking) to inspect your code for your errors. Do debugging by yourself.