9

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

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

然而,我们也被要求对用户发送的数据(几个简单的字段和一个二进制文件)进行签名,以便我们可以毫无疑问地证明哪个用户在我们的数据库中输入了每条记录。

我们的第一个想法是创建一个包含字段(以及文件的 md5,如果可能的话)的小文本签名,并使用证书的私钥对其进行加密,但是......

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

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

4

4 回答 4

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());
}
于 2010-10-11T11:17:08.713 回答
2

您需要询问您的法律部门这是否足够强大的“签名”,但每次发布字段时,服务器都会记录字段值和来自客户端证书握手的证书指纹。是的,这是“可伪造的”,因为任何了解指纹的人都可以在数据库中创建虚假记录,但是通过适当的数据库安全性,您可以删除该攻击向量并记录谁发布了什么(因为您不能伪造指纹客户端证书以 SSL 的两种方式身份验证)

于 2010-10-05T13:04:24.540 回答
1

我们无法访问证书的私钥来签署数据,

如果这不是真的,那么服务器可以记住证书本身,并在使用其他服务时将其用作真正的客户端。

即,将完全使使用客户端证书对客户端进行身份验证无效。

而且我不知道是否有任何方法可以在浏览器中对字段进行签名,

如何使用合适的客户端标签(例如 JavaScript、浏览器)提出这个问题以吸引合适的受众。(我确信它可以通过浏览器扩展或 ActiveX 对象来完成——但这会产生它自己的问题。)

于 2010-10-05T08:44:53.297 回答
1

有一个 JavaScript 方法 crypto.signText 允许使用客户端证书对任意文本进行签名。以下是一些文档签名表格​​示例。看来,目前只有 Firefox 支持它。

对于 IE,有 CAPICOM ActiveX 对象(可从 MS 下载)。是它的用法示例。

我不确定在不同的浏览器和操作系统版本中是否支持这些功能,您可能需要检查您的配置。

于 2010-10-10T20:16:05.067 回答