PeculiarVentures / fortify

Fortify enables web applications to use smart cards, local certificate stores and do certificate enrollment. This is the desktop application repository.
https://fortifyapp.com
Other
114 stars 33 forks source link

Signing with private key on smart card #347

Open DanialHuckabee opened 3 years ago

DanialHuckabee commented 3 years ago

Hi,

I'm working the example provided at https://github.com/PeculiarVentures/fortify-examples/blob/gh-pages/example5.html. Sample code gets private key to sign data.

const key = await GetCertificateKey("private", provider, $("certificates").value);

But the smart card I'm using doesn't allow to get private key.

Then I have tried pkcs11js library to use private key handle for signing and successfully signed with the code below.

pkcs11.C_FindObjectsInit(session,
        [
            { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PRIVATE_KEY },
            { type: pkcs11js.CKA_KEY_TYPE, value: pkcs11js.CKK_RSA }
        ]);
var hObject = pkcs11.C_FindObjects(session);
pkcs11.C_SignInit(session, { mechanism: pkcs11js.CKM_RSA_PKCS }, hObject);
var rsaPkcsSignature = pkcs11.C_Sign(session, new Buffer("Incomming message 1"), Buffer.alloc(1024));

Is there a way to sign with private key handle through Fortify?

Thank you very much.

rmhrisk commented 3 years ago

It should work fine what smart card are you using?

Does it work here:

https://fortifyapp.com/developers/examples/signing

DanialHuckabee commented 3 years ago

Smart card is AKIS, I've added ATR value to card.json. Fortify can successfully read certificate from smart card.

While signing from https://fortifyapp.com/developers/examples/signing it gives error below.

issue

Sharing Fortify log file contents below.

{"message":"Server: New session connect https://cdpn.io","level":"info"} {"message":"Server: Push session to stack","level":"info"} {"message":"Server: Cannot parse MessageSignedProtocol","level":"info"} {"message":"Server: Initialize secure session origin:https://cdpn.io id:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 authorized:true","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 server/isLoggedIn","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider/action/info","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider/action/getCrypto","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider/action/getCrypto reader:'Windows CryptoAPI' name:'Windows CryptoAPI' id:38a91044067c4e0e099f132c1f4695d57ba133a7","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider:38a91044067c4e0e099f132c1f4695d57ba133a7 crypto/isLoggedIn","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider:38a91044067c4e0e099f132c1f4695d57ba133a7 crypto/keyStorage/keys","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider:38a91044067c4e0e099f132c1f4695d57ba133a7 crypto/certificateStorage/keys","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider:38a91044067c4e0e099f132c1f4695d57ba133a7 crypto/certificateStorage/getItem","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider:38a91044067c4e0e099f132c1f4695d57ba133a7 crypto/certificateStorage/getItem","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider/action/getCrypto","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider/action/getCrypto reader:'OMNIKEY AG Smart Card Reader USB 0' name:'AKIS' id:47996ab59872436170a332b9dc077158c2458b3f7ad36e35c4d741dca73027d4","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider:47996ab59872436170a332b9dc077158c2458b3f7ad36e35c4d741dca73027d4 crypto/isLoggedIn","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider:47996ab59872436170a332b9dc077158c2458b3f7ad36e35c4d741dca73027d4 crypto/keyStorage/keys","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider:47996ab59872436170a332b9dc077158c2458b3f7ad36e35c4d741dca73027d4 crypto/certificateStorage/keys","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider:47996ab59872436170a332b9dc077158c2458b3f7ad36e35c4d741dca73027d4 crypto/certificateStorage/getItem","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider/action/getCrypto","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider/action/getCrypto reader:'OMNIKEY AG Smart Card Reader USB 0' name:'AKIS' id:47996ab59872436170a332b9dc077158c2458b3f7ad36e35c4d741dca73027d4","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider:47996ab59872436170a332b9dc077158c2458b3f7ad36e35c4d741dca73027d4 crypto/certificateStorage/getItem","level":"info"} {"message":"Server: session:9bfafa41c8f3a5f187dcfb96cf3b95a8ccd6d6e33e0fc8c46c5bb02002eae4a5 provider:47996ab59872436170a332b9dc077158c2458b3f7ad36e35c4d741dca73027d4 crypto/keyStorage/getItem","level":"info"} {"message":"Error: CKR_ATTRIBUTE_TYPE_INVALID:18\n at Error (native) PKCS11::C_GetAttributeValue:447\n at i.getAttribute (C:\Program Files\Fortify\resources\app.asar\out\main.js:18:573304)\n at i.get (C:\Program Files\Fortify\resources\app.asar\out\main.js:18:573624)\n at i.onAssign (C:\Program Files\Fortify\resources\app.asar\out\main.js:18:414812)\n at new s (C:\Program Files\Fortify\resources\app.asar\out\main.js:16:155259)\n at new i (C:\Program Files\Fortify\resources\app.asar\out\main.js:18:414656)\n at t.KeyStorage. (C:\Program Files\Fortify\resources\app.asar\out\main.js:32:215078)\n at Generator.next ()\n at C:\Program Files\Fortify\resources\app.asar\out\main.js:16:1616\n at new Promise ()\n at Module.l (C:\Program Files\Fortify\resources\app.asar\out\main.js:16:1361)","level":"error"} {"message":"Server: New session connect https://tools.fortifyapp.com","level":"info"} {"message":"Server: Push session to stack","level":"info"} {"message":"Server: Cannot parse MessageSignedProtocol","level":"info"} {"message":"Server: Initialize secure session origin:https://tools.fortifyapp.com id:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 authorized:true","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 server/isLoggedIn","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider/action/info","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider/action/getCrypto","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider/action/getCrypto reader:'Windows CryptoAPI' name:'Windows CryptoAPI' id:38a91044067c4e0e099f132c1f4695d57ba133a7","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider:38a91044067c4e0e099f132c1f4695d57ba133a7 crypto/isLoggedIn","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider/action/getCrypto","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider/action/getCrypto reader:'OMNIKEY AG Smart Card Reader USB 0' name:'AKIS' id:47996ab59872436170a332b9dc077158c2458b3f7ad36e35c4d741dca73027d4","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider:47996ab59872436170a332b9dc077158c2458b3f7ad36e35c4d741dca73027d4 crypto/isLoggedIn","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider/action/getCrypto","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider/action/getCrypto reader:'Windows CryptoAPI' name:'Windows CryptoAPI' id:38a91044067c4e0e099f132c1f4695d57ba133a7","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider:38a91044067c4e0e099f132c1f4695d57ba133a7 crypto/isLoggedIn","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider:38a91044067c4e0e099f132c1f4695d57ba133a7 crypto/keyStorage/keys","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider:38a91044067c4e0e099f132c1f4695d57ba133a7 crypto/certificateStorage/keys","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider:38a91044067c4e0e099f132c1f4695d57ba133a7 crypto/certificateStorage/getItem","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider:38a91044067c4e0e099f132c1f4695d57ba133a7 crypto/certificateStorage/getItem","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider:38a91044067c4e0e099f132c1f4695d57ba133a7 crypto/certificateStorage/export","level":"info"} {"message":"Server: session:b7adad6eb22a187823e0f136174e5d62fb70260ba8c1c00f5cf55b867e68e036 provider:38a91044067c4e0e099f132c1f4695d57ba133a7 crypto/certificateStorage/export","level":"info"}

microshine commented 3 years ago

Please try signing on https://peculiarventures.github.io/fortify-examples/example5.html and https://codesandbox.io/s/fortify-demo-2b9x8

DanialHuckabee commented 3 years ago

Both of them gives the same error. Annotation 2020-07-23 163232

And Fortify log.

{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider/action/getCrypto","level":"info"}
{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider/action/getCrypto reader:'ACS ACR39U ICC Reader 0' name:'AKIS' id:9e3b415dc192c7ff742e68921778879e13c6a93646c7292bec4f3cb916564582","level":"info"}
{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider:9e3b415dc192c7ff742e68921778879e13c6a93646c7292bec4f3cb916564582 crypto/isLoggedIn","level":"info"}
{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider:9e3b415dc192c7ff742e68921778879e13c6a93646c7292bec4f3cb916564582 crypto/keyStorage/keys","level":"info"}
{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider:9e3b415dc192c7ff742e68921778879e13c6a93646c7292bec4f3cb916564582 crypto/certificateStorage/keys","level":"info"}
{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider:9e3b415dc192c7ff742e68921778879e13c6a93646c7292bec4f3cb916564582 crypto/certificateStorage/getItem","level":"info"}
{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider/action/getCrypto","level":"info"}
{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider/action/getCrypto reader:'ACS ACR39U ICC Reader 0' name:'AKIS' id:9e3b415dc192c7ff742e68921778879e13c6a93646c7292bec4f3cb916564582","level":"info"}
{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider:9e3b415dc192c7ff742e68921778879e13c6a93646c7292bec4f3cb916564582 crypto/isLoggedIn","level":"info"}
{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider/action/getCrypto","level":"info"}
{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider/action/getCrypto reader:'ACS ACR39U ICC Reader 0' name:'AKIS' id:9e3b415dc192c7ff742e68921778879e13c6a93646c7292bec4f3cb916564582","level":"info"}
{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider:9e3b415dc192c7ff742e68921778879e13c6a93646c7292bec4f3cb916564582 crypto/isLoggedIn","level":"info"}
{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider:9e3b415dc192c7ff742e68921778879e13c6a93646c7292bec4f3cb916564582 crypto/certificateStorage/getItem","level":"info"}
{"message":"Server: session:f0430df22b280821f08299a85af727de02b93714b36d3336a90e9fc2d593730c provider:9e3b415dc192c7ff742e68921778879e13c6a93646c7292bec4f3cb916564582 crypto/keyStorage/getItem","level":"info"}
{"message":"Error: CKR_ATTRIBUTE_TYPE_INVALID:18\n    at Error (native) PKCS11::C_GetAttributeValue:447\n    at i.getAttribute (C:\\Program Files\\Fortify\\resources\\app.asar\\out\\main.js:18:573304)\n    at i.get (C:\\Program Files\\Fortify\\resources\\app.asar\\out\\main.js:18:573624)\n    at i.onAssign (C:\\Program Files\\Fortify\\resources\\app.asar\\out\\main.js:18:414812)\n    at new s (C:\\Program Files\\Fortify\\resources\\app.asar\\out\\main.js:16:155259)\n    at new i (C:\\Program Files\\Fortify\\resources\\app.asar\\out\\main.js:18:414656)\n    at t.KeyStorage.<anonymous> (C:\\Program Files\\Fortify\\resources\\app.asar\\out\\main.js:32:215078)\n    at Generator.next (<anonymous>)\n    at C:\\Program Files\\Fortify\\resources\\app.asar\\out\\main.js:16:1616\n    at new Promise (<anonymous>)\n    at Module.l (C:\\Program Files\\Fortify\\resources\\app.asar\\out\\main.js:16:1361)","level":"error"}
microshine commented 3 years ago

@DanialHuckabee Fortify uses node-webcrypto-p11 module

Please try this code it must point to the problematic attribute

const { Crypto } = require("node-webcrypto-p11");

const library = "/path/to/your/pkcs11.dll";

async function getPrivateKeyAsync(crypto, cert) {
  const certIndex = await crypto.certStorage.indexOf(cert);
  const [, , certId] = certIndex.split("-");

  const indexes = await crypto.keyStorage.keys();
  for (const index of indexes) {
    const [type, handle, id] = index.split("-");
    if (type === "private" && id === certId) {
      return await crypto.keyStorage.getItem(index);
    }
  }
  return null;
}

async function main() {
  const crypto = new Crypto({
    library,
    slot: 0,
    // pin: "PIN", // if needed
  });

  // Print all certificate
  const certIndexes = await crypto.certStorage.keys();
  for (const certIndex of certIndexes) {
    const cert = await crypto.certStorage.getItem(certIndex);
    console.log(certIndex, cert.subjectName);

    try {
      const privateKey = await getPrivateKeyAsync(crypto, cert);
      console.log("Private key:", privateKey ? privateKey.algorithm.name : null);
    } catch (e) {
      console.error(e)
      console.log("Private key: null")
    }
  }
}

main().catch(e => console.error(e));
microshine commented 3 years ago

I think the problem is in public exponent or modules getting for private key algorithm

ferikeem commented 3 years ago

I have the same issue. Card details: #276.

I have tried the code @microshine provided, and it works, logging: Private key: RSASSA-PKCS1-v1_5.

Algorithm public exponent is [1,0,1]. Could this be the problem? Wikipedia

There is no known attack against small public exponents such as e = 3, provided that the proper padding is used. Coppersmith's Attack has many applications in attacking RSA specifically if the public exponent e is small and if the encrypted message is short and not padded. 65537 is a commonly used value for e; this value can be regarded as a compromise between avoiding potential small exponent attacks and still allowing efficient encryptions (or signature verification). The NIST Special Publication on Computer Security (SP 800-78 Rev 1 of August 2007) does not allow public exponents e smaller than 65537, but does not state a reason for this restriction.

Otherwise the privateKey object looks fine, with a few exceptions in p11Object property:

Any idea where the problem might be?