java rsa 转pem_RSA加密xml格式秘钥转pem格式 | 学步园

本文介绍如何使用Java将XML格式的RSA密钥转换为PEM格式。通过解析XML文件,提取关键节点信息,然后利用这些信息生成RSA公钥或私钥,并将其编码为PEM格式。
摘要由CSDN通过智能技术生成

最近项目里有一个任务需求用到RSA加密,对方提供的是XML格式的秘钥,而我们使用python进行加密,在网上找了一个py开源库,M2Crypto,里面的rsa函数参数只能传递pem格式的秘钥,因此需要转换秘钥格式。在网上试了很多方法都不行,最后找到一个java的代码,测试成功。贴上代码,有时间可以移植到python里。

import java.io.*;

import java.math.BigInteger;

import java.security.*;

import java.security.spec.*;

import java.security.cert.*;

import java.security.interfaces.*;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import org.xml.sax.SAXException;

import org.xml.sax.SAXParseException;

import org.w3c.dom.*;

import org.w3c.dom.DOMException;

/**

* Converts a private or public RSA key from the XML Security format (used also

* in .NET) to the RSA key format in PEM format.

*

* The output key is written on standard output.

*

* In case of private key, the output format is the "traditional" format of the

* key, i.e. NOT the newer PKCS#8 format. The output keys are unencrypted. To

* convert to PKCS#8 and/or encrypt the private key, use openssl with the

* -topk8 option:

* openssl pkcs8 -topk8 -in privkey_rsa.pem -out privkey.pem

*

* Created by matous.borak@platanus.cz, 2008.

* See http://www.platanus.cz/blog/xml_key_to_pem_en.html

*

* Heavily inspired by the PvkConvert utility made by Michel Gallant, see

* http://www.jensign.com/JavaScience/PvkConvert/. Thanks for it!

*

*/

public class XMLSec2PEM {

private static final int PRIVATE_KEY = 1;

private static final int PUBLIC_KEY = 2;

private static final String[] PRIVATE_KEY_XML_NODES = { "Modulus", "Exponent", "P", "Q", "DP", "DQ", "InverseQ", "D" };

private static final String[] PUBLIC_KEY_XML_NODES = { "Modulus", "Exponent" };

public static void main(String args[]) {

if (args.length != 1) {

System.out.println("Usage:\n java XMLSec2PEM ");

System.exit(0) ;

}

try {

Document XMLSecKeyDoc = parseXMLFile(args[0]);

System.out.print("Determining the key type: ");

int keyType = getKeyType(XMLSecKeyDoc);

if (keyType == PRIVATE_KEY || keyType == PUBLIC_KEY) {

System.out.println("seems to be a " + ( keyType == PRIVATE_KEY ? "private" : "public" ) + " XML Security key");

} else {

System.exit(1);

}

System.out.print("Checking the XML file structure: ");

if (checkXMLRSAKey(keyType, XMLSecKeyDoc)) {

System.out.println("OK");

} else {

System.exit(1);

}

String pem = "";

System.out.println("Outputting the resulting key:\n");

if (keyType == PRIVATE_KEY) {

pem = convertXMLRSAPrivateKeyToPEM(XMLSecKeyDoc);

System.out.println("-----BEGIN PRIVATE KEY-----");

System.out.println(pem);

System.out.println("-----END PRIVATE KEY-----");

} else {

pem = convertXMLRSAPublicKeyToPEM(XMLSecKeyDoc);

System.out.println("-----BEGIN PUBLIC KEY-----");

System.out.println(pem);

System.out.println("-----END PUBLIC KEY-----");

}

}

catch (Exception e) {

System.err.println(e);

}

}

private static int getKeyType(Document xmldoc) {

Node root = xmldoc.getFirstChild();

if (!root.getNodeName().equals("RSAKeyValue")) {

System.out.println("Expecting node, encountered ");

return 0;

}

NodeList children = root.getChildNodes();

if (children.getLength() == PUBLIC_KEY_XML_NODES.length) {

return PUBLIC_KEY;

}

return PRIVATE_KEY;

}

private static boolean checkXMLRSAKey(int keyType, Document xmldoc) {

Node root = xmldoc.getFirstChild();

NodeList children = root.getChildNodes();

String[] wantedNodes = {};

if (keyType == PRIVATE_KEY) {

wantedNodes = PRIVATE_KEY_XML_NODES;

} else {

wantedNodes = PUBLIC_KEY_XML_NODES;

}

for (int j = 0; j < wantedNodes.length; j++) {

String wantedNode = wantedNodes[j];

boolean found = false;

for (int i = 0; i < children.getLength(); i++) {

if (children.item(i).getNodeName().equals(wantedNode)) {

found = true;

break;

}

}

if (!found) {

System.out.println("Cannot find node ");

return false;

}

}

return true;

}

private static String convertXMLRSAPrivateKeyToPEM(Document xmldoc) {

Node root = xmldoc.getFirstChild();

NodeList children = root.getChildNodes();

BigInteger modulus = null, exponent = null, primeP = null, primeQ = null,

primeExponentP = null, primeExponentQ = null,

crtCoefficient = null, privateExponent = null;

for (int i = 0; i < children.getLength(); i++) {

Node node = children.item(i);

String textValue = node.getTextContent();

if (node.getNodeName().equals("Modulus")) {

modulus = new BigInteger(b64decode(textValue));

} else if (node.getNodeName().equals("Exponent")) {

exponent = new BigInteger(b64decode(textValue));

} else if (node.getNodeName().equals("P")) {

primeP = new BigInteger(b64decode(textValue));

} else if (node.getNodeName().equals("Q")) {

primeQ = new BigInteger(b64decode(textValue));

} else if (node.getNodeName().equals("DP")) {

primeExponentP = new BigInteger(b64decode(textValue));

} else if (node.getNodeName().equals("DQ")) {

primeExponentQ = new BigInteger(b64decode(textValue));

} else if (node.getNodeName().equals("InverseQ")) {

crtCoefficient = new BigInteger(b64decode(textValue));

} else if (node.getNodeName().equals("D")) {

privateExponent = new BigInteger(b64decode(textValue));

}

}

try {

RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec (

modulus, exponent, privateExponent, primeP, primeQ,

primeExponentP, primeExponentQ, crtCoefficient);

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

PrivateKey key = keyFactory.generatePrivate(keySpec);

return b64encode(key.getEncoded());

} catch (Exception e) {

System.out.println(e);

}

return null;

}

private static String convertXMLRSAPublicKeyToPEM(Document xmldoc) {

Node root = xmldoc.getFirstChild();

NodeList children = root.getChildNodes();

BigInteger modulus = null, exponent = null;

for (int i = 0; i < children.getLength(); i++) {

Node node = children.item(i);

String textValue = node.getTextContent();

if (node.getNodeName().equals("Modulus")) {

modulus = new BigInteger(b64decode(textValue));

} else if (node.getNodeName().equals("Exponent")) {

exponent = new BigInteger(b64decode(textValue));

}

}

try {

RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, exponent);

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

PublicKey key = keyFactory.generatePublic(keySpec);

return b64encode(key.getEncoded());

} catch (Exception e) {

System.out.println(e);

}

return null;

}

private static Document parseXMLFile(String filename) {

try {

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

DocumentBuilder builder = factory.newDocumentBuilder();

Document document = builder.parse( new File(filename) );

return document;

} catch(Exception e) {

System.err.println(e);

return null;

}

}

private static final String b64encode(byte[] data) {

sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder() ;

String b64str = enc.encodeBuffer(data).trim();

return b64str;

}

private static final byte[] b64decode(String data) {

try {

sun.misc.BASE64Decoder dec = new sun.misc.BASE64Decoder() ;

byte[] bytes = dec.decodeBuffer(data.trim());

return bytes;

} catch (IOException e) {

System.out.println("Exception caught when base64 decoding!" + e.toString());

}

return null;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值