Rob*_*ska 18 java xml cryptography digital-signature xml-signature
我正在尝试使用Java 对XML文档进行数字签名.我有一个实现使用一些引用,我发现在javax.xml.crypto.dsig包中使用各种实现.
不过,我目前的实现是像很多的例子我已经看了-这是相当繁琐,使用从不下23种不同的API类包括java.xml.crypto.dsig,javax.xml.transform,和java.security包,等等.感觉就像我进入了工厂工厂的土地,我花了好几个小时来弄清楚发生了什么.
我的问题是,有更简单的方法吗?如果我有公共/私人密钥文件,并且我想要添加<Signature/>到XML文档,那么是否有一个库让我调用类似的东西:
OutputStream signFile(InputStream xmlFile, File privateKey)
Run Code Online (Sandbox Code Playgroud)
...没有所有的XMLSignatureFactory/CanonicalizationMethod/DOMSignContext疯狂?
我不是非常精通密码术,而且像我这样的开发人员试图熟悉数字签名,Java提供的API似乎相当令人生畏.如果所有这些都是必要的,或者目前没有友好的API,那很好,我愿意接受这个作为答案.我只是想知道我是否在这里不必要地走上了艰难的道路.
Pas*_*ent 11
看看Apache XML Security.要使用该包生成并验证签名,请签出样本src_samples/org/apache/xml/security/samples/signature/.
Kir*_*rby 10
从Apache Santuario CreateSignature示例构建,我能想到的最短的事情就是这个.没有它main()和它的伴随output(),它是20行
import java.io.*;
import java.security.Key;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.io.IOUtils;
import org.apache.xml.security.Init;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.transforms.Transforms;
import org.apache.xml.security.utils.Constants;
import org.apache.xml.security.utils.ElementProxy;
import org.w3c.dom.Document;
public class CreateSignature {
private static final String PRIVATE_KEY_ALIAS = "test-alias";
private static final String PRIVATE_KEY_PASS = "test";
private static final String KEY_STORE_PASS = "test";
private static final String KEY_STORE_TYPE = "JKS";
public static void main(String... unused) throws Exception {
final InputStream fileInputStream = new FileInputStream("test.xml");
try {
output(signFile(fileInputStream, new File("keystore.jks")), "signed-test.xml");
}
finally {
IOUtils.closeQuietly(fileInputStream);
}
}
public static ByteArrayOutputStream signFile(InputStream xmlFile, File privateKeyFile) throws Exception {
final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlFile);
Init.init();
ElementProxy.setDefaultPrefix(Constants.SignatureSpecNS, "");
final KeyStore keyStore = loadKeyStore(privateKeyFile);
final XMLSignature sig = new XMLSignature(doc, null, XMLSignature.ALGO_ID_SIGNATURE_RSA);
final Transforms transforms = new Transforms(doc);
transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);
final Key privateKey = keyStore.getKey(PRIVATE_KEY_ALIAS, PRIVATE_KEY_PASS.toCharArray());
final X509Certificate cert = (X509Certificate)keyStore.getCertificate(PRIVATE_KEY_ALIAS);
sig.addKeyInfo(cert);
sig.addKeyInfo(cert.getPublicKey());
sig.sign(privateKey);
doc.getDocumentElement().appendChild(sig.getElement());
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS).canonicalizeSubtree(doc));
return outputStream;
}
private static KeyStore loadKeyStore(File privateKeyFile) throws Exception {
final InputStream fileInputStream = new FileInputStream(privateKeyFile);
try {
final KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
keyStore.load(fileInputStream, KEY_STORE_PASS.toCharArray());
return keyStore;
}
finally {
IOUtils.closeQuietly(fileInputStream);
}
}
private static void output(ByteArrayOutputStream signedOutputStream, String fileName) throws IOException {
final OutputStream fileOutputStream = new FileOutputStream(fileName);
try {
fileOutputStream.write(signedOutputStream.toByteArray());
fileOutputStream.flush();
}
finally {
IOUtils.closeQuietly(fileOutputStream);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我查看了用于签署 XML 文件的所有选项,并决定采用非标准方法。标准太冗长了。另外,我不需要与标准兼容——我只需要 XML 块上的签名。
“签署”XML 块的最简单方法可能是使用具有独立签名的 GPG。