Web 浏览器证书注册(CSR 生成)和证书下载到智能卡或 USB 令牌

Web Browser Certificate Enrollment (CSR Generation) and Certificate Download to Smartcard or USB Token

我正在为认证机构开发 Web 应用程序,作为其中的一部分,我需要

  1. 生成非对称密钥对 - 私钥和 Public 通过浏览器输入用户的智能卡,
  2. 创建证书签名请求 (CSR) 并将 CSR 发送到生成用户证书的证书颁发机构服务器。
  3. 然后CA Server会将用户的证书发送到浏览器,需要通过浏览器下载到用户的SmartCard或USB Token。

如何使用在现代浏览器中工作的 JavaScript 实现同样的效果?使用 ActiveX 和 JavaApplets 不是选项。

披露:我在 CISPL, Co. 工作,该公司开发 Signer.Digital 浏览器扩展

浏览器扩展可用于在 Windows 证书存储或智能卡或现代浏览器的 USB 令牌中注册证书(生成 CSR)和下载证书。浏览器扩展提供 JavaScript API,它反过来与本地机器上的主机应用程序 运行 对话,以在智能卡中执行所需的操作,并 returns 响应 JavaScript (或说用户网页)。

使用浏览器生成的 CSR Javascript API genCSR 可能会发布到 CA 服务器以生成证书,如果您需要自签名证书,则可能会发布到您的服务器。证书和信任 从服务器接收回的证书链可能会传递给 ImportCer 以导入证书存储、智能卡或 USB 令牌。

API 可用于 Signer.Digital 中的认证机构的浏览器扩展是:

  1. 检测连接的智能卡:(自动检测连接的智能卡或 USB 令牌)

SignerDigital.getPCSCReaders(onlyConnected = true) //列出PCSC Readers,如果要列出所有可用的readers,请将参数设置为false

示例:

try 
{
    var SmartcardReaders = await SignerDigital.getPCSCReaders();
    var SCReaders = JSON.parse(SmartcardReaders);
    console.log(SmartcardReaders);
    console.log(SCReaders.length);
    if (SCReaders.length > 0)
    {
        $("#selSmartcard").empty();     //selSmartcard is HTML dropdown selector
        for (var i = 0; i < SCReaders.length; i++) {
            //ReaderNames are cryptic, convert to user friendly smartcard name
            var SCName = SignerDigital.getSCNameByReaderName(SCReaders[i]);  //Map PCSC ReaderName to User friendly smartcard name
            $("#selSmartcard").append(new Option(SCName));
        }
        
        //If Windows, add "Windows Certificate Store"
        if (SignerDigital.OSName == "Windows")
            $("#selSmartcard").append(new Option("Windows Certificate Store"));

        $('#selSmartcard option:eq(1)')
    }
}
catch (ErrorMsg) {
    alert(ErrorMsg);
}
  1. 生成 CSR:(用于证书存储、智能卡或 USB 令牌中的证书注册)

SignerDigital.genCSR(PKCS11Lib, certSubject, certIssuer, keyBits = 2048, hasgAlgorithm = "SHA256", forceUserPinChangeIfDefault = false, , extensions = null)

执行密码策略,即。强制用户更改智能卡制造商设置的默认密码,将 forceUserPinChangeIfDefault 设置为 true

示例 extensions 参数值:

{"SubjectAlternativeName":"RFC822Name=cisplapp@gmail.com"} {"SubjectAlternativeName":"DNSName=signer.digital;DNSName=charteredinfo.com;DNSName=multidomaincert.test"} {"SubjectAlternativeName":"URI=https://web.signer.digital;URI=https://help.signer.digital"}

  1. 导入/下载证书(将用户证书和信任证书链导入证书存储、智能卡或 USB 令牌)

SignerDigital.importCer(PKCS11Lib, b64Payload, certIssuer)

Json 以上 b64Payload 参数的模型是:(以下模型的 Json 的 Base64)

public class ImportCertReq
{
    public string UserCertB64 ;     //May be null to just import Trust Chain
    public List<string> TrustChainB64;  //May be null to just import USer Certificate
}

Json 成功模型 importCer 承诺的响应是:

public class ImportCertResp
{
    public bool IsSuccessUserCertImport;
    public string UserCertImportOutcome; 
    public int TrustChainImportCount; 
    public string TrustChainImportOutcome; 
}

生成 CSR导入证书 api 使用智能卡或 USB 令牌的 PKCS#11 库实现 OS。因此,在使用这些 JavaScript API 之前,需要在用户的 windows 电脑上安装智能卡驱动程序。要使用 Windows 证书存储,请将 PKCS11Lib 作为“Microsoft 增强型 RSA 和 AES 加密提供程序”传递。

Signer.Digital 扩展中的其他有用的属性和方法

  1. SignerDigital.getHostDetails() //检查 SDHostVersion >= 2 以确保 genCSR 和 certImport API 正常工作

响应模型:

HostDetails 
{
    public string OS ;
    public string OSPlatform;
    public string SDHostType ;
    public string SDHostVersion ;
    public DateTime? UpdateCheckedOn ;
    public int CheckForUpdateAfterDays ;
}
  1. SignerDigital.OSName

  2. SignerDigital.OSSupported

  3. SignerDigital.getPkcsLibByProvider(提供商名称)

  4. SignerDigital.getSCNameByReaderName(ReaderName) //ReaderName 使用上面第 1 点中列出的 promise getPCSCReaders() 获得。

  5. SignerDigital.getPkcsLibBySCName(SCName)

其他证书、签名和Encryption/DecryptionJavaScriptAPI可以参考。这些 API 使用 Windows CSP,在 Linux 使用 PKCS#11。

以上API可现场测试Here

Signer.Digital 生成 CSR 并下载证书流程