我们有一个 C# 网络应用程序,用户将在其中使用存储在浏览器中的数字证书进行连接。
从我们看到的示例中,一旦我们启用 SSL,验证他们的身份将很容易,因为我们可以使用 Request.ClientCertificate 访问证书中的字段来检查用户名。
然而,我们也被要求对用户发送的数据(一些简单的字段和一个二进制文件)进行签名,以便我们可以毫无疑问地证明是哪个用户输入了我们数据库中的每条记录。
我们的第一个想法是创建一个包含字段(如果可能,还有文件的 md5)的小文本签名,并使用证书的私钥对其进行加密,但是......
据我所知,我们无法访问证书的私钥来对数据进行签名,我不知道是否有任何方法可以在浏览器中对字段进行签名,或者我们别无选择使用 Java 小程序。如果是后者,我们会怎么做(有没有开源的小程序可以使用?如果我们自己做一个会更好吗?)
当然,如果有任何方法可以使用我们可以从用户证书访问的数据来“签署”服务器中接收到的字段,那就更好了。但如果没有,我们将不胜感激有关解决问题的最佳方法的任何信息。
最佳答案
我建议你使用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());
}
关于c# - 使用用户证书以 Web 形式签署数据的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3047437/