1 Star 5 Fork 3

xiangyuecn / RSA-java

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
RSA_PEM.java 22.43 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
package com.github.xiangyuecn.rsajava;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.Base64;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* RSA PEM格式秘钥对的解析和导出
*
* GitHub:https://github.com/xiangyuecn/RSA-java
*
* https://github.com/xiangyuecn/RSA-java/blob/master/RSA_PEM.java
* 移植自:https://github.com/xiangyuecn/RSA-csharp/blob/master/RSA_PEM.cs
*/
public class RSA_PEM {
/**modulus 模数,公钥、私钥都有**/
public byte[] Key_Modulus;
/**publicExponent 公钥指数,公钥、私钥都有**/
public byte[] Key_Exponent;
/**privateExponent 私钥指数,只有私钥的时候才有**/
public byte[] Key_D;
//以下参数只有私钥才有 https://docs.microsoft.com/zh-cn/dotnet/api/system.security.cryptography.rsaparameters?redirectedfrom=MSDN&view=netframework-4.8
/**prime1,只有私钥的时候才有**/
public byte[] Val_P;
/**prime2,只有私钥的时候才有**/
public byte[] Val_Q;
/**exponent1,只有私钥的时候才有**/
public byte[] Val_DP;
/**exponent2,只有私钥的时候才有**/
public byte[] Val_DQ;
/**coefficient,只有私钥的时候才有**/
public byte[] Val_InverseQ;
private RSA_PEM() {}
/***
* 通过公钥和私钥构造一个PEM
* @param publicKey 必须提供公钥
* @param privateKeyOrNull 私钥可以不提供,导出的PEM就只包含公钥
**/
public RSA_PEM(RSAPublicKey publicKey, RSAPrivateKey privateKeyOrNull) {
this(
BigB(publicKey.getModulus())
, BigB(publicKey.getPublicExponent())
, privateKeyOrNull==null?null:BigB(privateKeyOrNull.getPrivateExponent())
);
}
/***
* 通过全量的PEM字段数据构造一个PEM,除了模数modulus和公钥指数exponent必须提供外,其他私钥指数信息要么全部提供,要么全部不提供(导出的PEM就只包含公钥)
* 注意:所有参数首字节如果是0,必须先去掉
*/
public RSA_PEM(byte[] modulus, byte[] exponent, byte[] d, byte[] p, byte[] q, byte[] dp, byte[] dq, byte[] inverseQ) {
Key_Modulus=modulus;
Key_Exponent=exponent;
if(d!=null){
Key_D=BigL(d, modulus.length);
int keyLen = modulus.length / 2;
Val_P=BigL(p, keyLen);
Val_Q=BigL(q, keyLen);
Val_DP=BigL(dp, keyLen);
Val_DQ=BigL(dq, keyLen);
Val_InverseQ=BigL(inverseQ, keyLen);
}
}
/***
* 通过公钥指数和私钥指数构造一个PEM,会反推计算出P、Q但和原始生成密钥的P、Q极小可能相同
* 注意:所有参数首字节如果是0,必须先去掉
* @param modulus 必须提供模数
* @param exponent 必须提供公钥指数
* @param dOrNull 私钥指数可以不提供,导出的PEM就只包含公钥
**/
public RSA_PEM(byte[] modulus, byte[] exponent, byte[] dOrNull) {
Key_Modulus=modulus;//modulus
Key_Exponent=exponent;//publicExponent
if(dOrNull!=null) {
Key_D=BigL(dOrNull, modulus.length);//privateExponent
//反推P、Q
BigInteger n = BigX(modulus);
BigInteger e = BigX(exponent);
BigInteger d = BigX(dOrNull);
BigInteger p = findFactor(e, d, n);
BigInteger q = n.divide(p);
if (p.compareTo(q) > 0) {
BigInteger t = p;
p = q;
q = t;
}
BigInteger exp1 = d.mod(p.subtract(BigInteger.ONE));
BigInteger exp2 = d.mod(q.subtract(BigInteger.ONE));
BigInteger coeff = q.modInverse(p);
int keyLen = modulus.length / 2;
Val_P=BigL(BigB(p), keyLen);//prime1
Val_Q=BigL(BigB(q), keyLen);//prime2
Val_DP=BigL(BigB(exp1), keyLen);//exponent1
Val_DQ=BigL(BigB(exp2), keyLen);//exponent2
Val_InverseQ=BigL(BigB(coeff), keyLen);//coefficient
}
}
/**秘钥位数**/
public int keySize(){
return Key_Modulus.length*8;
}
/**是否包含私钥**/
public boolean hasPrivate(){
return Key_D!=null;
}
/**得到公钥Java对象**/
public RSAPublicKey getRSAPublicKey() throws Exception {
RSAPublicKeySpec spec=new RSAPublicKeySpec(BigX(Key_Modulus), BigX(Key_Exponent));
KeyFactory factory=KeyFactory.getInstance("RSA");
return (RSAPublicKey)factory.generatePublic(spec);
}
/**得到私钥Java对象**/
public RSAPrivateKey getRSAPrivateKey() throws Exception {
if(Key_D==null) {
throw new Exception("当前为公钥,无法获得私钥");
}
RSAPrivateKeySpec spec=new RSAPrivateKeySpec(BigX(Key_Modulus), BigX(Key_D));
KeyFactory factory=KeyFactory.getInstance("RSA");
return (RSAPrivateKey)factory.generatePrivate(spec);
}
/**转成正整数,如果是负数,需要加前导0转成正整数**/
static public BigInteger BigX(byte[] bigb) {
if(bigb[0]<0) {
byte[] c=new byte[bigb.length+1];
System.arraycopy(bigb,0,c,1,bigb.length);
bigb=c;
}
return new BigInteger(bigb);
}
/**BigInt导出byte整数首字节>0x7F的会加0前导,保证正整数,因此需要去掉0**/
static public byte[] BigB(BigInteger bigx) {
byte[] val=bigx.toByteArray();
if(val[0]==0) {
byte[] c=new byte[val.length-1];
System.arraycopy(val,1,c,0,c.length);
val=c;
}
return val;
}
/**某些密钥参数可能会少一位(32个byte只有31个,目测是密钥生成器的问题,只在c#生成的密钥中发现这种参数,java中生成的密钥没有这种现象),直接修正一下就行;这个问题与BigB有本质区别,不能动BigB**/
static public byte[] BigL(byte[] bytes, int keyLen) {
if (keyLen - bytes.length == 1) {
byte[] c = new byte[bytes.length + 1];
System.arraycopy(bytes, 0, c, 1, bytes.length);
bytes = c;
}
return bytes;
}
/**
* 由n e d 反推 P Q
* 资料: https://stackoverflow.com/questions/43136036/how-to-get-a-rsaprivatecrtkey-from-a-rsaprivatekey
* https://v2ex.com/t/661736
***/
private static BigInteger findFactor(BigInteger e, BigInteger d, BigInteger n) {
BigInteger edMinus1 = e.multiply(d).subtract(BigInteger.ONE);
int s = edMinus1.getLowestSetBit();
BigInteger t = edMinus1.shiftRight(s);
long now=System.currentTimeMillis();
for (int aInt = 2; true; aInt++) {
if(aInt%10==0 && System.currentTimeMillis()-now>3000) {
throw new RuntimeException(T("推算RSA.P超时", "Estimated RSA.P timeout"));//测试最多循环2次,1024位的速度很快 8ms
}
BigInteger aPow = BigInteger.valueOf(aInt).modPow(t, n);
for (int i = 1; i <= s; i++) {
if (aPow.equals(BigInteger.ONE)) {
break;
}
if (aPow.equals(n.subtract(BigInteger.ONE))) {
break;
}
BigInteger aPowSquared = aPow.multiply(aPow).mod(n);
if (aPowSquared.equals(BigInteger.ONE)) {
return aPow.subtract(BigInteger.ONE).gcd(n);
}
aPow = aPowSquared;
}
}
}
/**
* 用PEM格式密钥对创建RSA,支持PKCS#1、PKCS#8格式的PEM
*/
static public RSA_PEM FromPEM(String pem) throws Exception {
RSA_PEM param=new RSA_PEM();
String base64 = _PEMCode.matcher(pem).replaceAll("");
byte[] dataX = Base64.getDecoder().decode(base64);//java byte是正负数
if (dataX == null) {
throw new Exception(T("PEM内容无效", "Invalid PEM content"));
}
short[] data=new short[dataX.length];//转成正整数的bytes数组,不然byte是负数难搞
for(int i=0;i<dataX.length;i++) {
data[i]=(short)(dataX[i]&0xff);
}
int[] idx = new int[] {0};
if (pem.contains("PUBLIC KEY")) {
/****使用公钥****/
//读取数据总长度
readLen(0x30, data, idx);
//检测PKCS8
int[] idx2 = new int[] {idx[0]};
if (eq(_SeqOID, data, idx)) {
//读取1长度
readLen(0x03, data, idx);
idx[0]++;//跳过0x00
//读取2长度
readLen(0x30, data, idx);
}else {
idx = idx2;
}
//Modulus
param.Key_Modulus = readBlock(data, idx);
//Exponent
param.Key_Exponent = readBlock(data, idx);
} else if (pem.contains("PRIVATE KEY")) {
/****使用私钥****/
//读取数据总长度
readLen(0x30, data, idx);
//读取版本号
if (!eq(_Ver, data, idx)) {
throw new Exception(T("PEM未知版本", "Unknown PEM version"));
}
//检测PKCS8
int[] idx2 = new int[] {idx[0]};
if (eq(_SeqOID, data, idx)) {
//读取1长度
readLen(0x04, data, idx);
//读取2长度
readLen(0x30, data, idx);
//读取版本号
if (!eq(_Ver, data, idx)) {
throw new Exception(T("PEM版本无效", "Invalid PEM version"));
}
} else {
idx = idx2;
}
//读取数据
param.Key_Modulus = readBlock(data, idx);
param.Key_Exponent = readBlock(data, idx);
int keyLen = param.Key_Modulus.length;
param.Key_D = BigL(readBlock(data, idx), keyLen);
keyLen = keyLen / 2;
param.Val_P = BigL(readBlock(data, idx), keyLen);
param.Val_Q = BigL(readBlock(data, idx), keyLen);
param.Val_DP = BigL(readBlock(data, idx), keyLen);
param.Val_DQ = BigL(readBlock(data, idx), keyLen);
param.Val_InverseQ = BigL(readBlock(data, idx), keyLen);
} else {
throw new Exception(T("pem需要BEGIN END标头", "pem requires BEGIN END header"));
}
return param;
}
static private Pattern _PEMCode = Pattern.compile("--+.+?--+|[\\s\\r\\n]+");
static private byte[] _SeqOID = new byte[] { 0x30, 0x0D, 0x06, 0x09, 0x2A, (byte)0x86, 0x48, (byte)0x86, (byte)0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
static private byte[] _Ver = new byte[] { 0x02, 0x01, 0x00 };
/**从数组start开始到指定长度复制一份**/
static private byte[] sub(short[] arr, int start, int count) {
byte[] val = new byte[count];
for (int i = 0; i < count; i++) {
val[i] = (byte)arr[start + i];
}
return val;
}
/**读取长度**/
static private int readLen(int first, short[] data, int[] idxO) throws Exception {
int idx=idxO[0];
try {
if (data[idx] == first) {
idx++;
if (data[idx] == 0x81) {
idx++;
return data[idx++];
} else if (data[idx] == 0x82) {
idx++;
return (((int)data[idx++]) << 8) + data[idx++];
} else if (data[idx] < 0x80) {
return data[idx++];
}
}
throw new Exception(T("PEM未能提取到数据", "Failed to extract data from PEM"));
}finally {
idxO[0]=idx;
}
}
/**读取块数据**/
static private byte[] readBlock(short[] data, int[] idxO) throws Exception {
int idx=idxO[0];
try {
int len = readLen(0x02, data, idxO);
idx=idxO[0];
if (data[idx] == 0x00) {
idx++;
len--;
}
byte[] val = sub(data, idx, len);
idx += len;
return val;
}finally {
idxO[0]=idx;
}
}
/**比较data从idx位置开始是否是byts内容**/
static private boolean eq(byte[] byts, short[] data, int[] idxO) {
int idx=idxO[0];
try {
for (int i = 0; i < byts.length; i++, idx++) {
if (idx >= data.length) {
return false;
}
if ((byts[i]&0xff) != data[idx]) {
return false;
}
}
return true;
}finally {
idxO[0]=idx;
}
}
/***
* 将当前PEM中的密钥对复制出一个新的PEM对象
* 。convertToPublic:等于true时含私钥的PEM将只返回公钥,仅含公钥的PEM不受影响
*/
public RSA_PEM CopyToNew(boolean convertToPublic) {
if (convertToPublic) {
return new RSA_PEM(Key_Modulus, Key_Exponent, null, null, null, null, null, null);
}
return new RSA_PEM(Key_Modulus, Key_Exponent, Key_D, Val_P, Val_Q, Val_DP, Val_DQ, Val_InverseQ);
}
/***
* 【不安全、不建议使用】对调交换公钥指数(Key_Exponent)和私钥指数(Key_D):把公钥当私钥使用(new.Key_D=this.Key_Exponent)、私钥当公钥使用(new.Key_Exponent=this.Key_D),返回一个新PEM对象;比如用于:私钥加密、公钥解密,这是非常规的用法
* 。当前对象必须含私钥,否则无法交换会直接抛异常
* 。注意:把公钥当私钥使用是非常不安全的,因为绝大部分生成的密钥的公钥指数为 0x10001(AQAB),太容易被猜测到,无法作为真正意义上的私钥
*/
public RSA_PEM SwapKey_Exponent_D__Unsafe() throws Exception {
if(Key_D==null) throw new Exception(T("SwapKey只支持私钥", "SwapKey only supports private keys"));
return new RSA_PEM(Key_Modulus, Key_D, Key_Exponent);
}
/***
* 将RSA中的密钥对转换成PEM PKCS#8格式
* 。convertToPublic:等于true时含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
* 。公钥如:-----BEGIN RSA PUBLIC KEY-----,私钥如:-----BEGIN RSA PRIVATE KEY-----
* 。似乎导出PKCS#1公钥用的比较少,PKCS#8的公钥用的多些,私钥#1#8都差不多
*/
public String ToPEM_PKCS1(boolean convertToPublic) throws Exception {
return ToPEM(convertToPublic, false, false);
}
/***
* 将RSA中的密钥对转换成PEM PKCS#8格式
* 。convertToPublic:等于true时含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
* 。公钥如:-----BEGIN PUBLIC KEY-----,私钥如:-----BEGIN PRIVATE KEY-----
*/
public String ToPEM_PKCS8(boolean convertToPublic) throws Exception {
return ToPEM(convertToPublic, true, true);
}
/***
* 将RSA中的密钥对转换成PEM格式
* 。convertToPublic:等于true时含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
* 。privateUsePKCS8:私钥的返回格式,等于true时返回PKCS#8格式(-----BEGIN PRIVATE KEY-----),否则返回PKCS#1格式(-----BEGIN RSA PRIVATE KEY-----),返回公钥时此参数无效;两种格式使用都比较常见
* 。publicUsePKCS8:公钥的返回格式,等于true时返回PKCS#8格式(-----BEGIN PUBLIC KEY-----),否则返回PKCS#1格式(-----BEGIN RSA PUBLIC KEY-----),返回私钥时此参数无效;一般用的多的是true PKCS#8格式公钥,PKCS#1格式公钥似乎比较少见
*/
public String ToPEM(boolean convertToPublic, boolean privateUsePKCS8, boolean publicUsePKCS8) throws Exception {
byte[] der = ToDER(convertToPublic, privateUsePKCS8, publicUsePKCS8);
if (this.Key_D==null || convertToPublic) {
String flag = " PUBLIC KEY";
if (!publicUsePKCS8) {
flag = " RSA" + flag;
}
return "-----BEGIN" + flag + "-----\n" + TextBreak(Base64.getEncoder().encodeToString(der), 64) + "\n-----END" + flag + "-----";
} else {
String flag = " PRIVATE KEY";
if (!privateUsePKCS8) {
flag = " RSA" + flag;
}
return "-----BEGIN" + flag + "-----\n" + TextBreak(Base64.getEncoder().encodeToString(der), 64) + "\n-----END" + flag + "-----";
}
}
/***
* 将RSA中的密钥对转换成DER格式,DER格式为PEM中的Base64文本编码前的二进制数据
* 。convertToPublic:等于true时含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
* 。privateUsePKCS8:私钥的返回格式,等于true时返回PKCS#8格式,否则返回PKCS#1格式,返回公钥时此参数无效;两种格式使用都比较常见
* 。publicUsePKCS8:公钥的返回格式,等于true时返回PKCS#8格式,否则返回PKCS#1格式,返回私钥时此参数无效;一般用的多的是true PKCS#8格式公钥,PKCS#1格式似乎比较少见公钥
*/
public byte[] ToDER(boolean convertToPublic, boolean privateUsePKCS8, boolean publicUsePKCS8) throws Exception {
//https://www.jianshu.com/p/25803dd9527d
//https://www.cnblogs.com/ylz8401/p/8443819.html
//https://blog.csdn.net/jiayanhui2877/article/details/47187077
//https://blog.csdn.net/xuanshao_/article/details/51679824
//https://blog.csdn.net/xuanshao_/article/details/51672547
ByteArrayOutputStream ms = new ByteArrayOutputStream();
if (this.Key_D==null || convertToPublic) {
/****生成公钥****/
//写入总字节数,不含本段长度,额外需要24字节的头,后续计算好填入
ms.write(0x30);
int index1 = ms.size();
//PKCS8 多一段数据
int index2 = -1, index3 = -1;
if (publicUsePKCS8) {
//固定内容
// encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
ms.write(_SeqOID);
//从0x00开始的后续长度
ms.write(0x03);
index2 = ms.size();
ms.write(0x00);
//后续内容长度
ms.write(0x30);
index3 = ms.size();
}
//写入Modulus
writeBlock(Key_Modulus, ms);
//写入Exponent
writeBlock(Key_Exponent, ms);
//计算空缺的长度
byte[] byts = ms.toByteArray();
if (index2 != -1) {
byts = writeLen(index3, byts, ms);
byts = writeLen(index2, byts, ms);
}
byts = writeLen(index1, byts, ms);
return byts;
} else {
/****生成私钥****/
//写入总字节数,后续写入
ms.write(0x30);
int index1 = ms.size();
//写入版本号
ms.write(_Ver);
//PKCS8 多一段数据
int index2 = -1, index3 = -1;
if (privateUsePKCS8) {
//固定内容
ms.write(_SeqOID);
//后续内容长度
ms.write(0x04);
index2 = ms.size();
//后续内容长度
ms.write(0x30);
index3 = ms.size();
//写入版本号
ms.write(_Ver);
}
//写入数据
writeBlock(Key_Modulus, ms);
writeBlock(Key_Exponent, ms);
writeBlock(Key_D, ms);
writeBlock(Val_P, ms);
writeBlock(Val_Q, ms);
writeBlock(Val_DP, ms);
writeBlock(Val_DQ, ms);
writeBlock(Val_InverseQ, ms);
//计算空缺的长度
byte[] byts = ms.toByteArray();
if (index2 != -1) {
byts = writeLen(index3, byts, ms);
byts = writeLen(index2, byts, ms);
}
byts = writeLen(index1, byts, ms);
return byts;
}
}
/**写入一个长度字节码**/
static private void writeLenByte(int len, ByteArrayOutputStream ms) {
if (len < 0x80) {
ms.write((byte)len);
} else if (len <= 0xff) {
ms.write(0x81);
ms.write((byte)len);
} else {
ms.write(0x82);
ms.write((byte)(len >> 8 & 0xff));
ms.write((byte)(len & 0xff));
}
}
/**写入一块数据**/
static private void writeBlock(byte[] byts, ByteArrayOutputStream ms) throws Exception {
boolean addZero = ((byts[0] & 0xff) >> 4) >= 0x8;
ms.write(0x02);
int len = byts.length + (addZero ? 1 : 0);
writeLenByte(len, ms);
if (addZero) {
ms.write(0x00);
}
ms.write(byts);
}
/**根据后续内容长度写入长度数据**/
static private byte[] writeLen(int index, byte[] byts, ByteArrayOutputStream ms) {
int len = byts.length - index;
ms.reset();
ms.write(byts, 0, index);
writeLenByte(len, ms);
ms.write(byts, index, len);
return ms.toByteArray();
}
/**把字符串按每行多少个字断行**/
static private String TextBreak(String text, int line) {
int idx = 0;
int len = text.length();
StringBuilder str = new StringBuilder();
while (idx < len) {
if (idx > 0) {
str.append('\n');
}
if (idx + line >= len) {
str.append(text.substring(idx));
} else {
str.append(text.substring(idx, idx+line));
}
idx += line;
}
return str.toString();
}
/***
* 将XML格式密钥转成PEM,支持公钥xml、私钥xml
*/
static public RSA_PEM FromXML(String xml) throws Exception {
RSA_PEM rtv=new RSA_PEM();
Matcher xmlM=xmlExp.matcher(xml);
if(!xmlM.find()) {
throw new Exception(T("XML内容不符合要求", "XML content does not meet requirements"));
}
Matcher tagM=xmlTagExp.matcher(xmlM.group(1));
Base64.Decoder dec=Base64.getDecoder();
while(tagM.find()) {
String tag=tagM.group(1);
String b64=tagM.group(2);
byte[] val=dec.decode(b64);
switch(tag) {
case "Modulus":rtv.Key_Modulus=val;break;
case "Exponent":rtv.Key_Exponent=val;break;
case "D":rtv.Key_D=val;break;
case "P":rtv.Val_P=val;break;
case "Q":rtv.Val_Q=val;break;
case "DP":rtv.Val_DP=val;break;
case "DQ":rtv.Val_DQ=val;break;
case "InverseQ":rtv.Val_InverseQ=val;break;
}
}
if(rtv.Key_Modulus==null || rtv.Key_Exponent==null) {
throw new Exception(T("XML公钥丢失", "Public key in XML is missing"));
}
if(rtv.Key_D!=null) {
if(rtv.Val_P==null || rtv.Val_Q==null || rtv.Val_DP==null || rtv.Val_DQ==null || rtv.Val_InverseQ==null) {
return new RSA_PEM(rtv.Key_Modulus, rtv.Key_Exponent, rtv.Key_D);
}
}
return rtv;
}
static private Pattern xmlExp=Pattern.compile("\\s*<RSAKeyValue>([<>\\/\\+=\\w\\s]+)</RSAKeyValue>\\s*");
static private Pattern xmlTagExp=Pattern.compile("<(.+?)>\\s*([^<]+?)\\s*</");
/***
* 将RSA中的密钥对转换成XML格式
* ,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响
*/
public String ToXML(boolean convertToPublic) {
Base64.Encoder enc=Base64.getEncoder();
StringBuilder str=new StringBuilder();
str.append("<RSAKeyValue>");
str.append("<Modulus>"+enc.encodeToString(Key_Modulus)+"</Modulus>");
str.append("<Exponent>"+enc.encodeToString(Key_Exponent)+"</Exponent>");
if (this.Key_D==null || convertToPublic) {
/****生成公钥****/
//NOOP
} else {
/****生成私钥****/
str.append("<P>"+enc.encodeToString(Val_P)+"</P>");
str.append("<Q>"+enc.encodeToString(Val_Q)+"</Q>");
str.append("<DP>"+enc.encodeToString(Val_DP)+"</DP>");
str.append("<DQ>"+enc.encodeToString(Val_DQ)+"</DQ>");
str.append("<InverseQ>"+enc.encodeToString(Val_InverseQ)+"</InverseQ>");
str.append("<D>"+enc.encodeToString(Key_D)+"</D>");
}
str.append("</RSAKeyValue>");
return str.toString();
}
/***
* 简版多语言支持,根据当前语言{@link #Lang()}返回中文或英文
*/
static public String T(String zh, String en) {
return "zh".equals(Lang()) ? zh : en;
}
static private String _lang;
/**
* 简版多语言支持,取值:zh(简体中文)、en(English-US),默认根据系统取值
*/
static public String Lang() {
if(_lang==null) {
String locale=Locale.getDefault().toString().replace('_', '-').toLowerCase();
if(Pattern.compile("\\b(zh|cn)\\b").matcher(locale).find()) {
_lang = "zh";
} else {
_lang = "en";
}
}
return _lang;
}
/**
* 简版多语言支持,可设置值:zh(简体中文)、en(English-US)
*/
static public void SetLang(String lang) {
_lang=lang;
}
}
1
https://gitee.com/xiangyuecn/RSA-java.git
git@gitee.com:xiangyuecn/RSA-java.git
xiangyuecn
RSA-java
RSA-java
master

搜索帮助