如何在Java中使用RSAPrivateKeySpec类从字符串创建RSA私钥?

huangapple go评论67阅读模式
英文:

How to create RSA PrivateKey from string with RSAPrivateKeySpec class in Java?

问题

以下是已翻译的部分:

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import javax.crypto.Cipher;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

// 解密函数
static String Decrypt(String encodedString, PrivateKey privKey) {
    try {
        Cipher cipher = Cipher.getInstance(cipherInstancename);
        cipher.init(Cipher.DECRYPT_MODE, privKey);
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encodedString));
        return new String(decrypted, "UTF-8");
    } catch (Exception err) {
        return err.fillInStackTrace().toString();
    }
}

// 加密函数
static String Encrypt(String encodedString, PublicKey pubKey) {
    try {
        Cipher cipher = Cipher.getInstance(cipherInstancename);
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        byte[] plainBytes = new String(encodedString).getBytes("UTF-8");
        byte[] cipherData = cipher.doFinal(plainBytes);
        String encryptedString = Base64.getEncoder().encodeToString(cipherData);
        return encryptedString;
    } catch (Exception err) {
        return err.fillInStackTrace().toString();
    }
}

// 第一种方式生成私钥
static PrivateKey firstPrivateKey(String privateKeyStr) throws Exception {
    // ... (详细内容请参考原文)
}

// 第一种方式生成公钥
static PublicKey firstPublicKey(String publicKeyStr) throws Exception {
    // ... (详细内容请参考原文)
}

// 第二种方式生成公钥
static PublicKey secondPublicKey(String publicKString, String publicExponentStr) throws Exception {
    // ... (详细内容请参考原文)
}

// 第二种方式生成私钥
static PrivateKey secondPrivateKey(String privateKString, String privateExponentStr) throws Exception {
    // ... (详细内容请参考原文)
}

// 更新部分,生成公钥和私钥以及模数
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
KeyPair kp = kpg.generateKeyPair();
String publicKeyStr = Base64.getEncoder().encodeToString(kp.getPublic().getEncoded());
String privateKeyStr = Base64.getEncoder().encodeToString(kp.getPrivate().getEncoded());

KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// ... (详细内容请参考原文)

BigInteger publicKeyModulus = rsaPub.getModulus();
BigInteger publicKeyExponent = rsaPub.getPublicExponent();
BigInteger privateKeyModulus = rsaPrv.getModulus();
BigInteger privateKeyExponent = rsaPrv.getPrivateExponent();

String nModulusPublic = Base64.getUrlEncoder().encodeToString(publicKeyModulus.toByteArray());
String eExponentPublic = Base64.getUrlEncoder().encodeToString(publicKeyExponent.toByteArray());
String nModulusPrivate = Base64.getUrlEncoder().encodeToString(privateKeyModulus.toByteArray());
String eExponentPrivate = Base64.getUrlEncoder().encodeToString(privateKeyExponent.toByteArray());

System.out.println(publicKeyStr);
System.out.println(privateKeyStr);
System.out.println(nModulusPublic);
System.out.println(eExponentPublic);
System.out.println(nModulusPrivate);
System.out.println(eExponentPrivate);

有关原始代码中的问题,请查看更新的部分内容以获取更多细节。

英文:

I have the below information and want to generate a public and private key in RSA (Java).

    String pubKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJXFRUWMDJZ+moC/VbcAXoY5dDxOruwI2B+B+YZRHSRRTKPyd9v0HTqdLeVgufLu/cSxlZAKtZDp9mfgyNdbY9ECAwEAAQ==";
String privKey = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAlcVFRYwMln6agL9VtwBehjl0PE6u7AjYH4H5hlEdJFFMo/J32/QdOp0t5WC58u79xLGVkAq1kOn2Z+DI11tj0QIDAQABAkBC1Bp71OkNAgL47edWWADVja9y9X0R70RYkst/hpQlTrjN4QxzN4k4gCqqdFkno2LfacRO7igMQuVEmYujfkbNAiEA/lU1CyW9J65FXSObsBLxqlNpFw79B2EKUkT6o7b2Ez8CIQCWwJlIyDaoXt7CrvTrPDpok7U93ZKmDPiRjjXDPsGU7wIhAJ6pITIXFO2QNg1ojVNGPiR3bHPKEedsjjfMeF9xYAmZAiAQnfpHg4pC1PJJE2/73g+yJ1X7E8ludE+R+9MBSpGcEQIgBWaVSyTx4e+gSulT93vnMpVsYmiwe53e5t4Uxs+cgSE=";
String nModulusPublic = "AJXFRUWMDJZ-moC_VbcAXoY5dDxOruwI2B-B-YZRHSRRTKPyd9v0HTqdLeVgufLu_cSxlZAKtZDp9mfgyNdbY9E=";
String eExponentPublic = "AQAB";
String nModulusPrivate = "AJXFRUWMDJZ-moC_VbcAXoY5dDxOruwI2B-B-YZRHSRRTKPyd9v0HTqdLeVgufLu_cSxlZAKtZDp9mfgyNdbY9E=";
String eExponentPrivate = "QtQae9TpDQIC-O3nVlgA1Y2vcvV9Ee9EWJLLf4aUJU64zeEMczeJOIAqqnRZJ6Ni32nETu4oDELlRJmLo35GzQ==";

These are main Encryption and decryption functions :

static String Decrypt(String encodedString,PrivateKey privKey) {
try {
Cipher cipher = Cipher.getInstance(cipherInstancename);
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encodedString));
return new String(decrypted, "UTF-8");
} catch (Exception err) {
return err.fillInStackTrace().toString();
}
}
static String Encrypt(String encodedString,PublicKey pubKey) {
try {
Cipher cipher = Cipher.getInstance(cipherInstancename);
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] plainBytes = new String(encodedString).getBytes("UTF-8");
byte[] cipherData = cipher.doFinal(plainBytes);
String encryptedString = Base64.getEncoder().encodeToString(cipherData);
return encryptedString;
} catch (Exception err) {
return err.fillInStackTrace().toString();
}
}

If I create PrivateKey and PublicKey with below function everything works great:

 static PrivateKey firstPrivateKey(String privateKeyStr) throws Exception {
byte[] keyBytes = Base64.getDecoder().decode(privateKeyStr.getBytes(StandardCharsets.UTF_8));
PKCS8EncodedKeySpec specPrivate = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey fileGeneratedPrivateKey = keyFactory.generatePrivate(specPrivate);
RSAPrivateKey rsaPrv  = (RSAPrivateKey)(fileGeneratedPrivateKey);
return  rsaPrv;
}
static PublicKey firstPublicKey(String publicKeyStr) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] keyBytes = Base64.getDecoder().decode(publicKeyStr.getBytes(StandardCharsets.UTF_8));
X509EncodedKeySpec specPublic = new X509EncodedKeySpec(keyBytes);
PublicKey fileGeneratedPublicKey = keyFactory.generatePublic(specPublic);
RSAPublicKey rsaPub  = (RSAPublicKey)(fileGeneratedPublicKey);
return  rsaPub;
}

But I want to create them by this way with below function but decryption does not work:

 static PublicKey secondPublicKey(String publicKString,String publicExponentStr) throws Exception {
byte[] modulusBytes = Base64.getDecoder().decode(publicKString);
byte[] exponentBytes = Base64.getDecoder().decode(publicExponentStr);
BigInteger modulus = new BigInteger(1, modulusBytes);
BigInteger exponent = new BigInteger(1, exponentBytes);
RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(rsaPubKey);
return pubKey;
}
static PrivateKey secondPrivateKey(String privateKString,String privateExponentStr) throws Exception {
byte[] modulusBytes = Base64.getDecoder().decode(privateKString);
byte[] exponentBytes = Base64.getDecoder().decode(privateExponentStr);
BigInteger modulus = new BigInteger(1, modulusBytes);
BigInteger exponent = new BigInteger(1, exponentBytes);
RSAPrivateKeySpec privSpec = new RSAPrivateKeySpec(modulus,exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey privKey = fact.generatePrivate(privSpec);
return privKey;
}

Using firstPrivateKey and firstPublicKey key generators and work nice:

   String a = Encrypt("test",firstPrivateKey(pubKey));
String b = Decrypt(a, firstPublicKey(privKey));
System.out.println(b);

Using second functions and does not work:

 String a = Encrypt("test",secondPublicKey(pubKey,eExponentPublic));
String b = Decrypt(a, secondPrivateKey(privKey,eExponentPrivate));
System.out.println(b);

What's the problem with secondPublicKey and secondPrivateKey functions?

Update:

I generate all keys and Modulus from this code, It seems my decoding is not ok:

    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
// RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(1024, RSAKeyGenParameterSpec.F4);
kpg.initialize( 512 );
KeyPair kp = kpg.generateKeyPair();
String publicKeyStr = Base64.getEncoder().encodeToString(kp.getPublic().getEncoded());
String privateKeyStr = Base64.getEncoder().encodeToString(kp.getPrivate().getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] keyBytes = Base64.getDecoder().decode(publicKeyStr.getBytes(StandardCharsets.UTF_8));
X509EncodedKeySpec specPublic = new X509EncodedKeySpec(keyBytes);
PublicKey fileGeneratedPublicKey = keyFactory.generatePublic(specPublic);
RSAPublicKey rsaPub  = (RSAPublicKey)(fileGeneratedPublicKey);
keyBytes = Base64.getDecoder().decode(privateKeyStr.getBytes(StandardCharsets.UTF_8));
PKCS8EncodedKeySpec specPrivate = new PKCS8EncodedKeySpec(keyBytes);
PrivateKey fileGeneratedPrivateKey = keyFactory.generatePrivate(specPrivate);
RSAPrivateKey rsaPrv  = (RSAPrivateKey)(fileGeneratedPrivateKey);
BigInteger publicKeyModulus = rsaPub.getModulus();
BigInteger publicKeyExponent  = rsaPub.getPublicExponent();
BigInteger privateKeyModulus = rsaPrv.getModulus();
BigInteger privateKeyExponent  = rsaPrv.getPrivateExponent();
String nModulusPublic=Base64.getUrlEncoder().encodeToString(publicKeyModulus.toByteArray());
String eExponentPublic=Base64.getUrlEncoder().encodeToString(publicKeyExponent.toByteArray());
String nModulusPrivate=Base64.getUrlEncoder().encodeToString(privateKeyModulus.toByteArray());
String eExponentPrivate=Base64.getUrlEncoder().encodeToString(privateKeyExponent.toByteArray());
System.out.println(publicKeyStr);
System.out.println(privateKeyStr);
System.out.println( nModulusPublic);
System.out.println(eExponentPublic);
System.out.println( nModulusPrivate);
System.out.println(eExponentPrivate);

答案1

得分: 3

A related public and private key have the same modulus. Therefore the distinction between nModulusPublic and nModulusPrivate is actually not necessary (unlike the public and private exponent).

secondPublicKey() and secondPrivateKey() expect the modulus (nModulusPublic or the identical nModulusPrivate) as first argument. Instead, the entire key (pubKey or privKey) is passed, which causes the error. If the modulus is passed instead, it works.

By the way, modulus and exponent are Base64url encoded and must first be converted to the standard Base64 encoding (- -> + and _ -> /). Alternatively, the Base64url decoder can be used in secondPublicKey() or secondPrivateKey() (Base64.getUrlDecoder()).

Since the two public or private keys are identical (only with different formats), any public/private key combination is possible for encryption/decryption:

String pubKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJXFRUWMDJZ+moC/VbcAXoY5dDxOruwI2B+B+YZRHSRRTKPyd9v0HTqdLeVgufLu/cSxlZAKtZDp9mfgyNdbY9ECAwEAAQ==";
String privKey = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAlcVFRYwMln6agL9VtwBehjl0PE6u7AjYH4H5hlEdJFFMo/J32/QdOp0t5WC58u79xLGVkAq1kOn2Z+DI11tj0QIDAQABAkBC1Bp71OkNAgL47edWWADVja9y9X0R70RYkst/hpQlTrjN4QxzN4k4gCqqdFkno2LfacRO7igMQuVEmYujfkbNAiEA/lU1CyW9J65FXSObsBLxqlNpFw79B2EKUkT6o7b2Ez8CIQCWwJlIyDaoXt7CrvTrPDpok7U93ZKmDPiRjjXDPsGU7wIhAJ6pITIXFO2QNg1ojVNGPiR3bHPKEedsjjfMeF9xYAmZAiAQnfpHg4pC1PJJE2/73g+yJ1X7E8ludE+R+9MBSpGcEQIgBWaVSyTx4e+gSulT93vnMpVsYmiwe53e5t4Uxs+cgSE=";
String nModulusPublic = "AJXFRUWMDJZ-moC_VbcAXoY5dDxOruwI2B-B-YZRHSRRTKPyd9v0HTqdLeVgufLu_cSxlZAKtZDp9mfgyNdbY9E=".replace("-", "+").replace("", "/");
String eExponentPublic = "AQAB".replace("-", "+").replace("
", "/");
String nModulusPrivate = "AJXFRUWMDJZ-moC_VbcAXoY5dDxOruwI2B-B-YZRHSRRTKPyd9v0HTqdLeVgufLu_cSxlZAKtZDp9mfgyNdbY9E=".replace("-", "+").replace("", "/");
String eExponentPrivate = "QtQae9TpDQIC-O3nVlgA1Y2vcvV9Ee9EWJLLf4aUJU64zeEMczeJOIAqqnRZJ6Ni32nETu4oDELlRJmLo35GzQ==".replace("-", "+").replace("
", "/");

String a, b;

// first/first
a = Encrypt("test", firstPublicKey(pubKey));
b = Decrypt(a, firstPrivateKey(privKey));
System.out.println(b);

// second/second
a = Encrypt("test", secondPublicKey(nModulusPublic, eExponentPublic));
b = Decrypt(a, secondPrivateKey(nModulusPrivate, eExponentPrivate));
System.out.println(b);

// first/second
a = Encrypt("test", firstPublicKey(pubKey));
b = Decrypt(a, secondPrivateKey(nModulusPrivate, eExponentPrivate));
System.out.println(b);

// second/first
a = Encrypt("test", secondPublicKey(nModulusPublic, eExponentPublic));
b = Decrypt(a, firstPrivateKey(privKey));
System.out.println(b);

Note that there is a typo in the posted code: Encrypt is used in combination with firstPrivateKey() and Decrypt in combination with firstPublicKey().

英文:

A related public and private key have the same modulus. Therefore the distinction between nModulusPublic and nModulusPrivate is actually not necessary (unlike the public and private exponent).

secondPublicKey() and secondPrivateKey() expect the modulus (nModulusPublic or the identical nModulusPrivate) as first argument. Instead, the entire key (pubKey or privKey) is passed, which causes the error. If the modulus is passed instead, it works.

By the way, modulus and exponent are Base64url encoded and must first be converted to the standard Base64 encoding (- -> + and _ -> /). Alternatively the Base64url decoder can be used in secondPublicKey() or secondPrivateKey() (Base64.getUrlDecoder()).

Since the two public or private keys are identical (only with different formats) any public/private key combination is possible for encryption/deryption:

String pubKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJXFRUWMDJZ+moC/VbcAXoY5dDxOruwI2B+B+YZRHSRRTKPyd9v0HTqdLeVgufLu/cSxlZAKtZDp9mfgyNdbY9ECAwEAAQ==";
String privKey = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAlcVFRYwMln6agL9VtwBehjl0PE6u7AjYH4H5hlEdJFFMo/J32/QdOp0t5WC58u79xLGVkAq1kOn2Z+DI11tj0QIDAQABAkBC1Bp71OkNAgL47edWWADVja9y9X0R70RYkst/hpQlTrjN4QxzN4k4gCqqdFkno2LfacRO7igMQuVEmYujfkbNAiEA/lU1CyW9J65FXSObsBLxqlNpFw79B2EKUkT6o7b2Ez8CIQCWwJlIyDaoXt7CrvTrPDpok7U93ZKmDPiRjjXDPsGU7wIhAJ6pITIXFO2QNg1ojVNGPiR3bHPKEedsjjfMeF9xYAmZAiAQnfpHg4pC1PJJE2/73g+yJ1X7E8ludE+R+9MBSpGcEQIgBWaVSyTx4e+gSulT93vnMpVsYmiwe53e5t4Uxs+cgSE=";
String nModulusPublic = "AJXFRUWMDJZ-moC_VbcAXoY5dDxOruwI2B-B-YZRHSRRTKPyd9v0HTqdLeVgufLu_cSxlZAKtZDp9mfgyNdbY9E=".replace("-", "+").replace("_","/");
String eExponentPublic = "AQAB".replace("-", "+").replace("_","/");
String nModulusPrivate = "AJXFRUWMDJZ-moC_VbcAXoY5dDxOruwI2B-B-YZRHSRRTKPyd9v0HTqdLeVgufLu_cSxlZAKtZDp9mfgyNdbY9E=".replace("-", "+").replace("_","/");
String eExponentPrivate = "QtQae9TpDQIC-O3nVlgA1Y2vcvV9Ee9EWJLLf4aUJU64zeEMczeJOIAqqnRZJ6Ni32nETu4oDELlRJmLo35GzQ==".replace("-", "+").replace("_","/");	
String a, b;
// first/first
a = Encrypt("test", firstPublicKey(pubKey));
b = Decrypt(a, firstPrivateKey(privKey));
System.out.println(b);
// second/second
a = Encrypt("test", secondPublicKey(nModulusPublic, eExponentPublic));
b = Decrypt(a, secondPrivateKey(nModulusPrivate, eExponentPrivate));
System.out.println(b);
// first/second
a = Encrypt("test", firstPublicKey(pubKey));
b = Decrypt(a, secondPrivateKey(nModulusPrivate, eExponentPrivate));
System.out.println(b);
// second/first
a = Encrypt("test", secondPublicKey(nModulusPublic, eExponentPublic));
b = Decrypt(a, firstPrivateKey(privKey));
System.out.println(b);

Note that there is a typo in the posted code: Encrypt is used in combination with firstPrivateKey() and Decrypt in combination with firstPublicKey().

huangapple
  • 本文由 发表于 2020年8月29日 21:41:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/63647609.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定