作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我遇到以下问题。我用java编写了一个简单的测试类来加密和解密XML文件。但是当我尝试解密从光盘加载的文件时,出现以下错误:
Oct 04, 2017 5:41:49 PM com.sun.org.apache.xml.internal.security.encryption.XMLCipher doFinal
SEVERE: Source element unexpectedly null...
Exception in thread "main" java.lang.NullPointerException
at com.sun.org.apache.xml.internal.security.encryption.XMLCipher$Factory.newEncryptedData(XMLCipher.java:2190)
at com.sun.org.apache.xml.internal.security.encryption.XMLCipher.decryptToByteArray(XMLCipher.java:1677)
at com.sun.org.apache.xml.internal.security.encryption.XMLCipher.decryptElement(XMLCipher.java:1616)
at com.sun.org.apache.xml.internal.security.encryption.XMLCipher.doFinal(XMLCipher.java:936)
at EncryptionDecryption.decryptDocument(EncryptionDecryption.java:134)
at EncryptionDecryption.main(EncryptionDecryption.java:42)
类(class):
import com.sun.org.apache.xml.internal.security.encryption.XMLCipher;
import com.sun.org.apache.xml.internal.security.utils.EncryptionConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
public class EncryptionDecryption {
public static void main(String[] args) throws Exception {
com.sun.org.apache.xml.internal.security.Init.init();
byte[] key = ("i love stackoverflow").getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-512");
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
Document document = getDocument("classes.xml");
Document encryptedDoc = encryptDocument(document, secretKeySpec,
XMLCipher.AES_256);
saveDocumentTo(encryptedDoc, "encrypted.xml");
encryptedDoc = getDocument("encrypted.xml");
Document decryptedDoc = decryptDocument(encryptedDoc,
secretKeySpec, XMLCipher.AES_256);
saveDocumentTo(decryptedDoc, "decrypted.xml");
}
public static void saveSecretKey(SecretKey secretKey, String fileName) {
byte[] keyBytes = secretKey.getEncoded();
File keyFile = new File(fileName);
FileOutputStream fOutStream = null;
try {
fOutStream = new FileOutputStream(keyFile);
fOutStream.write(keyBytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fOutStream != null) {
try {
fOutStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static String keyToString(SecretKey secretKey) {
/* Get key in encoding format */
byte encoded[] = secretKey.getEncoded();
/*
* Encodes the specified byte array into a String using Base64 encoding
* scheme
*/
String encodedKey = Base64.getEncoder().encodeToString(encoded);
return encodedKey;
}
public static SecretKey getSecretKey(String algorithm) {
KeyGenerator keyGenerator = null;
try {
keyGenerator = KeyGenerator.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return keyGenerator.generateKey();
}
public static Document getDocument(String xmlFile) throws Exception {
/* Get the instance of BuilderFactory class. */
DocumentBuilderFactory builder = DocumentBuilderFactory.newInstance();
/* Instantiate DocumentBuilder object. */
DocumentBuilder docBuilder = builder.newDocumentBuilder();
/* Get the Document object */
Document document = docBuilder.parse(xmlFile);
return document;
}
public static void saveDocumentTo(Document document, String fileName)
throws Exception {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(new File(fileName));
transformer.transform(source, result);
}
public static Document encryptDocument(Document document, SecretKey secretKey, String algorithm) throws Exception {
/* Get Document root element */
Element rootElement = document.getDocumentElement();
String algorithmURI = algorithm;
XMLCipher xmlCipher = XMLCipher.getInstance(algorithmURI);
/* Initialize cipher with given secret key and operational mode */
xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
/* Process the contents of document */
xmlCipher.doFinal(document, rootElement, true);
return document;
}
public static Document decryptDocument(Document document, SecretKey secretKey, String algorithm) throws Exception {
Element encryptedDataElement = (Element) document.
getElementsByTagNameNS(EncryptionConstants.EncryptionSpecNS, EncryptionConstants._TAG_ENCRYPTEDDATA).item(0);
XMLCipher xmlCipher = XMLCipher.getInstance();
xmlCipher.init(XMLCipher.DECRYPT_MODE, secretKey);
xmlCipher.doFinal(document, encryptedDataElement);
return document;
}
}
当我注释掉第 40 行时:
/*encryptedDoc = getDocument("encrypted.xml");*/
然后问题就不会出现了。因此,就像当我在程序运行时使用加密的 xml 文档而不从光盘加载时,XMLCipher 会成功解密它:)
最佳答案
您需要将 DocumentBuilder
设置为命名空间感知:
public static Document getDocument(String xmlFile) throws Exception {
/* Get the instance of BuilderFactory class. */
DocumentBuilderFactory builder = DocumentBuilderFactory.newInstance();
builder.setNamespaceAware(true);
// ...
如果没有此设置,库将无法找到加密文档时存储的元数据。
关于java - 从光盘加载时无法解密 XML 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46569053/
我想用 list-style-type: disc; 列出一些程序。 但是列表项没有这个“disc”并且有滚动条,我不知道为什么......看这里(Link)。 它应该只是一个带有光盘图标的列表,每个
使用 cygwin 终端,我的 .bashrc 中有以下内容: export WINHOME="/cygdrive/c/Users/userName" export TUTORING="$WINHOM
我创建了一个别名,以免每次我移动到一个新目录时都写 ls: alias cl='cd_(){ cd "$@" && ls; }; cd_' 假设我有一个名为“下载”的文件夹(我当然碰巧有),所以我只需
我是一名优秀的程序员,十分优秀!