使用用户证书以Web表单签名数据的最佳方式

sal*_*iza 9 javascript c# browser asp.net-mvc x509certificate

我们有一个C#Web应用程序,用户可以使用存储在浏览器中的数字证书进行连接.

从我们看到的示例中,一旦启用SSL,验证其身份将很容易,因为我们可以使用Request.ClientCertificate访问证书中的字段来检查用户的名称.

但是,我们还要求签署用户发送的数据(一些简单的字段和一个二进制文件),这样我们就可以毫无疑问地证明哪个用户输入了我们数据库中的每个记录.

我们的第一个想法是创建一个小文本签名,包括字段(如果可能的话,还有文件的md5),并使用证书的私钥加密它,但是......

据我所知,我们无法访问证书的私钥来签署数据,我不知道是否有任何方式在浏览器中对字段进行签名,或者除了使用Java之外别无选择小程序.如果是后者,我们将如何做到(我们可以使用任何开源小程序吗?如果我们自己创建一个小程序会更好吗?)

当然,如果有任何方法可以使用我们可以从用户证书访问的数据"签署"服务器中收到的字段,那会更好.但如果没有,任何关于解决问题的最佳方法的信息将不胜感激.

Sas*_*sha 8

我建议你使用java-applet.这种方法适用于所有浏览器.我们在项目中使用它.要签署用户数据,您需要使用JCA API(http://download.oracle.com/javase/1.4.2/docs/guide/security/CryptoSpec.html#Signature).此外,您还需要解决从java访问Windows证书存储区的问题.

你可以用这种方式解决它:

KeyStore keystore = KeyStore.getInstance("Windows-MY", "SunMSCAPI");

keystore.load(null, null);

HashMap<String,String> userPublicKeys = new HashMap<String,String>();

Enumeration<String> aliasesEnum = keystore.aliases();

if (!aliasesEnum.hasMoreElements())
    throw new Exception("No certificate!");

// list through windows personal store
while (aliasesEnum.hasMoreElements()) 
{
   String alias = aliasesEnum.nextElement();

   boolean isKey = keystore.isKeyEntry(alias);

   if (isKey)
   {
       BASE64Encoder encoder = new BASE64Encoder();
       encoder.encode(keystore.getCertificate(alias).getEncoded());

       userPublicKeys.put(alias, encoder.encode(keystore.getCertificate(alias).getEncoded()));
       System.out.println("Entry alias: " + alias); 
   }

   // sign
   PrivateKey privateKey = (PrivateKey) keystore.getKey(alias,null);           

   Provider provider = keystore.getProvider();
   // data to signed
   byte[] data ="test data".getBytes();
   // Signing the data
   Signature sig = Signature.getInstance("SHA1withRSA", provider);
   sig.initSign(privateKey);

   sig.update(data);
   byte[] signature = sig.sign();

   System.out.println(ByteArrayToFromHexDigits.bytesToHexString(signature).toUpperCase());
}
Run Code Online (Sandbox Code Playgroud)