RSA XML格式秘钥转Pem并解密

45 篇文章 11 订阅

一.XML格式秘钥转Pem格式

package VerifyLicense;

import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;

public class RSAXmlToPem {

    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" };
    
    
    /**
     * xml格式秘钥转为Pem格式秘钥
     * @param xmlStr  xml格式私钥字符串
     * @return pem格式秘钥
     */
    public static String transXmlStrToPem (String xmlStr){
        String pem = "";
        try {
            Document XMLSecKeyDoc = parseXMLStr(xmlStr);
            int keyType = getKeyType(XMLSecKeyDoc);
            if (keyType == PRIVATE_KEY) {
                pem = convertXMLRSAPrivateKeyToPEM(XMLSecKeyDoc);
            } else {
                pem = convertXMLRSAPublicKeyToPEM(XMLSecKeyDoc);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(pem);
        return pem;
    }

    /**
     * xml格式秘钥转为Pem格式秘钥
     * @param path  xml格式私钥文件地址
     * @return pem格式秘钥
     */
    public static String transXmlTotPem(String path){
        String pem = "";
        try {
            Document XMLSecKeyDoc = parseXMLFile(path);
            int keyType = getKeyType(XMLSecKeyDoc);

            if (keyType == PRIVATE_KEY) {
                pem = convertXMLRSAPrivateKeyToPEM(XMLSecKeyDoc);
            } else {
                pem = convertXMLRSAPublicKeyToPEM(XMLSecKeyDoc);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return pem;
    }

    /**
     * 获得秘钥类型
     * @param xmldoc
     * @return
     */
    private static int getKeyType(Document xmldoc) {

        Node root = xmldoc.getFirstChild();
        if (!root.getNodeName().equals("RSAKeyValue")) {
            System.out.println("Expecting <RSAKeyValue> node, encountered <" + root.getNodeName() + ">");
            return 0;
        }
        NodeList children = root.getChildNodes();
        if (children.getLength() == PUBLIC_KEY_XML_NODES.length) {
            return PUBLIC_KEY;
        }
        return PRIVATE_KEY;

    }

    /**
     * 检查秘钥是否符合格式
     * @param keyType
     * @param xmldoc
     * @return
     */
    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 <" + wantedNode + ">");
                return false;
            }
        }
        return true;

    }

    /**
     *  将xml格式私钥转为PEM格式
     * @param xmldoc
     * @return
     */
    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) {
            e.printStackTrace();
        }
        return null;

    }

    /**
     *  将xml格式公钥转为PEM格式
     * @param xmldoc
     * @return
     */
    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) {
            e.printStackTrace();
        }
        return null;

    }

    /**
     * 将xml格式字符串格式化城Document格式
     * @param xmlStr
     * @return
     */
    private static Document parseXMLStr(String xmlStr) {
        try {
            InputStream  in=new ByteArrayInputStream(xmlStr.getBytes());
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(in);
            return document;
        } catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将某个包含xml的文件转换为Document格式
     * @param filename
     * @return
     */
    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) {
            e.printStackTrace();
            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) {
            e.printStackTrace();
        }
        return null;
    }
    
}

二.RSA私钥解密,支持Pem格式秘钥,xml格式不支持

pom中加入依赖:

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.12</version>
        </dependency>

package VerifyLicense;

import java.io.*;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.*;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;


public class RSAUtil {
    
    /**
     * RSA私钥解密
     * @param strPath 加密字符串文件路径
     * @param privateKeyPath xml私钥文件路径
     * @return 铭文
     */
    public static String decryptXmlRSA(String strPath, String privateKeyPath){
        String str = readFile(strPath);
        String privateKey = RSAXmlToPem.transXmlTotPem(privateKeyPath);
        String code = "";
        try {
            code = decrypt(str,privateKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return code;
    }

    /**
     * RSA私钥解密
     * @param str 加密字符串
     * @param xmlPrivateKey xml格式私钥字符串
     * @return 铭文
     */
    public static String decryptXmlStrRSA(String str, String xmlPrivateKey){
        String code = "";
        String privateKey = RSAXmlToPem.transXmlStrToPem(xmlPrivateKey);
        try {
            code = decrypt(str,privateKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return code;
    }


    /**
     * RSA私钥解密,支持Pem格式秘钥,xml格式不支持
     * @param str 加密字符串
     * @param privateKey 私钥
     * @return 铭文
     * @throws Exception 解密过程中的异常信息
     */
    public static String decrypt(String str, String privateKey) throws Exception{
        //64位解码加密后的字符串
        byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
        //base64编码的私钥
        byte[] decoded = Base64.decodeBase64(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        //RSA解密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        String outStr = new String(cipher.doFinal(inputByte));
        return outStr;
    }

    /**
     * 读取文件内容
     * @param filepath
     * @return
     */
    public static String readFile(String filepath) {
        FileReader re = null;
        BufferedReader buff = null;
        String line = "";
        try {
            File file = new File(filepath);
            re = new FileReader(file);
            buff = new BufferedReader(re);
            String tempString = null;
            while ((tempString = buff.readLine()) != null) {
                line += tempString;
            }
            return line;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                re.close();
                buff.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return line;
    }


    /**
     * 寻找证书文件
     * 证书文件一般会放在某个特定的文件夹,并以特定格式结尾,在不知道该验证证书文件完整名称的时候
     * 我们寻找以某文件结尾的文件,前提是,该文件夹下只有一个该格式文件,否则应该以全名检索
     * @param path
     * @param endStr
     * @return
     */
    public static String getEncryptionFile(String path,String endStr) {
        File file = new File(path);
        File[] array = file.listFiles();

        for (int i = 0; i < array.length; i++) {
            if (array[i].isFile()) {
                if (array[i].getPath().endsWith(endStr)){
                    return array[i].getPath();
                }
            } else if (array[i].isDirectory()) {
                continue;
            }
        }
        return "";
    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纯洁的小魔鬼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值