Load RSA public key from file
Below is the relevant information from the link which Zaki provided.
Generate a 2048-bit RSA private key
$ openssl genrsa -out private_key.pem 2048
Convert private Key to PKCS#8 format (so Java can read it)
$ openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt
Output public key portion in DER format (so Java can read it)
$ openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der
Private key
import java.nio.file.*;
import java.security.*;
import java.security.spec.*;
public class PrivateKeyReader {
public static PrivateKey get(String filename)
throws Exception {
byte[] keyBytes = Files.readAllBytes(Paths.get(filename));
PKCS8EncodedKeySpec spec =
new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
}
Public key
import java.nio.file.*;
import java.security.*;
import java.security.spec.*;
public class PublicKeyReader {
public static PublicKey get(String filename)
throws Exception {
byte[] keyBytes = Files.readAllBytes(Paths.get(filename));
X509EncodedKeySpec spec =
new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
}
How to Load RSA Private Key From File
You need to convert your private key to PKCS8 format using following command:
openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key_file -nocrypt > pkcs8_key
After this your java program can read it.
How to read an RSA key from file
A combination of pem.Decode
and x509.ParsePKCS1PrivateKey
should do the trick:
package main
import (
"crypto/x509"
"encoding/pem"
"fmt"
)
func main() {
pemString := `-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDLets8+7M+iAQAqN/5BVyCIjhTQ4cmXulL+gm3v0oGMWzLupUS
v8KPA+Tp7dgC/DZPfMLaNH1obBBhJ9DhS6RdS3AS3kzeFrdu8zFHLWF53DUBhS92
5dCAEuJpDnNizdEhxTfoHrhuCmz8l2nt1pe5eUK2XWgd08Uc93h5ij098wIDAQAB
AoGAHLaZeWGLSaen6O/rqxg2laZ+jEFbMO7zvOTruiIkL/uJfrY1kw+8RLIn+1q0
wLcWcuEIHgKKL9IP/aXAtAoYh1FBvRPLkovF1NZB0Je/+CSGka6wvc3TGdvppZJe
rKNcUvuOYLxkmLy4g9zuY5qrxFyhtIn2qZzXEtLaVOHzPQECQQDvN0mSajpU7dTB
w4jwx7IRXGSSx65c+AsHSc1Rj++9qtPC6WsFgAfFN2CEmqhMbEUVGPv/aPjdyWk9
pyLE9xR/AkEA2cGwyIunijE5v2rlZAD7C4vRgdcMyCf3uuPcgzFtsR6ZhyQSgLZ8
YRPuvwm4cdPJMmO3YwBfxT6XGuSc2k8MjQJBAI0+b8prvpV2+DCQa8L/pjxp+VhR
Xrq2GozrHrgR7NRokTB88hwFRJFF6U9iogy9wOx8HA7qxEbwLZuhm/4AhbECQC2a
d8h4Ht09E+f3nhTEc87mODkl7WJZpHL6V2sORfeq/eIkds+H6CJ4hy5w/bSw8tjf
sz9Di8sGIaUbLZI2rd0CQQCzlVwEtRtoNCyMJTTrkgUuNufLP19RZ5FpyXxBO5/u
QastnN77KfUwdj3SJt44U/uh1jAIv4oSLBr8HYUkbnI8
-----END RSA PRIVATE KEY-----`
block, _ := pem.Decode([]byte(pemString))
key, _ := x509.ParsePKCS1PrivateKey(block.Bytes)
fmt.Println(key.N)
}
If what you are sitting on is a PKCS#8 encoded key, instead you would do something like the following:
func main() {
pemString := `-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKhPSTDs4cpKfnMc
p86fCkpnuER7bGc+mGkhkw6bE+BnROfrDCFBSjrENLS5JcsenANQ1kYGt9iVW2fd
ZAWUdDoj+t7g6+fDpzY1BzPSUls421Dmu7joDPY8jSdMzFCeg7Lyj0I36bJJ7ooD
VPW6Q0XQcb8FfBiFPAKuY4elj/YDAgMBAAECgYBo2GMWmCmbM0aL/KjH/KiTawMN
nfkMY6DbtK9/5LjADHSPKAt5V8ueygSvI7rYSiwToLKqEptJztiO3gnls/GmFzj1
V/QEvFs6Ux3b0hD2SGpGy1m6NWWoAFlMISRkNiAxo+AMdCi4I1hpk4+bHr9VO2Bv
V0zKFxmgn1R8qAR+4QJBANqKxJ/qJ5+lyPuDYf5s+gkZWjCLTC7hPxIJQByDLICw
iEnqcn0n9Gslk5ngJIGQcKBXIp5i0jWSdKN/hLxwgHECQQDFKGmo8niLzEJ5sa1r
spww8Hc2aJM0pBwceshT8ZgVPnpgmITU1ENsKpJ+y1RTjZD6N0aj9gS9UB/UXdTr
HBezAkEAqkDRTYOtusH9AXQpM3zSjaQijw72Gs9/wx1RxOSsFtVwV6U97CLkV1S+
2HG1/vn3w/IeFiYGfZXLKFR/pA5BAQJAbFeu6IaGM9yFUzaOZDZ8mnAqMp349t6Q
DB5045xJxLLWsSpfJE2Y12H1qvO1XUzYNIgXq5ZQOHBFbYA6txBy/QJBAKDRQN47
6YClq9652X+1lYIY/h8MxKiXpVZVncXRgY6pbj4pmWEAM88jra9Wq6R77ocyECzi
XCqi18A/sl6ymWc=
-----END PRIVATE KEY-----`
block, _ := pem.Decode([]byte(pemString))
parseResult, _ := x509.ParsePKCS8PrivateKey(block.Bytes)
key := parseResult.(*rsa.PrivateKey)
fmt.Println(key.N)
}
How to read a rsa public key file in java?
Try this method:
/**
* reads a public key from a file
* @param filename name of the file to read
* @param algorithm is usually RSA
* @return the read public key
* @throws Exception
*/
public PublicKey getPemPublicKey(String filename, String algorithm) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
String temp = new String(keyBytes);
String publicKeyPEM = temp.replace("-----BEGIN PUBLIC KEY-----\n", "");
publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----", "");
BASE64Decoder b64 = new BASE64Decoder();
byte[] decoded = b64.decodeBuffer(publicKeyPEM);
X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);
KeyFactory kf = KeyFactory.getInstance(algorithm);
return kf.generatePublic(spec);
}
source: Load RSA public key from file
how to load Private Key from .key file
I hope this will help you to generate the token.
keep the .key
or .der
file into classpath src/main/resources
.
public class JWTClientService {
public String generateJWTToken(ProjectConfig jwtConfig) {
return Jwts.builder()
.setSubject(jwtConfig.getSubject())
.setIssuer(jwtConfig.getIssuer())
.setExpiration(getExpiryDate(jwtConfig.getTokenExpiryUnit(), jwtConfig.getTokenExpiryFrequency()))
.setAudience(jwtConfig.getAudience())
.claim(jwtConfig.getClaimKey(), Boolean.valueOf(jwtConfig.getClaimValue()))
.signWith(SignatureAlgorithm.RS512, privateKey(jwtConfig))
.compact();
}
private Date getExpiryDate(String tokenExp, String tokenExpFreq) {
Calendar calendar = Calendar.getInstance();
int expiry = Integer.parseInt(tokenExp);
switch (tokenExpFreq.toLowerCase()) {
case "second": {
calendar.add(Calendar.SECOND, expiry);
break;
}
case "minute": {
calendar.add(Calendar.MINUTE, expiry);
break;
}
case "hour": {
calendar.add(Calendar.HOUR, expiry);
break;
}
case "day": {
calendar.add(Calendar.DATE, expiry);
break;
}
case "month": {
calendar.add(Calendar.MONTH, expiry);
break;
}
default: {
calendar.add(Calendar.HOUR, expiry);
break;
}
}
return calendar.getTime();
}
private PrivateKey privateKey(ProjectConfig jwtConfig) {
PrivateKey privateKey = null;
try {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(jwtConfig.getKeyPath());
ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
assert inputStream != null;
IOUtils.copy(inputStream, byteOutputStream);
byte[] privKeyByteArray = byteOutputStream.toByteArray();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privKeyByteArray);
KeyFactory keyFactory = KeyFactory.getInstance(jwtConfig.getKeyAlgorithm());
privateKey = keyFactory.generatePrivate(keySpec);
} catch (Exception ex) {
throw new RuntimeException("Unable to generate private key..." + ex.getMessage());
}
return privateKey;
}
}
Find the Project config class:
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ProjectConfig {
private String clientId;
private String clientSecret;
private String jwtTokenUrl;
private String keyAlgorithm;
private String keyPath;
private String subject;
private String issuer;
private String audience;
private String claimKey;
private String claimValue;
private String tokenExpiryFrequency;
private String tokenExpiryUnit;
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getClientSecret() {
return clientSecret;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
public String getJwtTokenUrl() {
return jwtTokenUrl;
}
public void setJwtTokenUrl(String jwtTokenUrl) {
this.jwtTokenUrl = jwtTokenUrl;
}
public String getKeyAlgorithm() {
return keyAlgorithm;
}
public void setKeyAlgorithm(String keyAlgorithm) {
this.keyAlgorithm = keyAlgorithm;
}
public String getKeyPath() {
return keyPath;
}
public void setKeyPath(String keyPath) {
this.keyPath = keyPath;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getIssuer() {
return issuer;
}
public void setIssuer(String issuer) {
this.issuer = issuer;
}
public String getAudience() {
return audience;
}
public void setAudience(String audience) {
this.audience = audience;
}
public String getClaimKey() {
return claimKey;
}
public void setClaimKey(String claimKey) {
this.claimKey = claimKey;
}
public String getClaimValue() {
return claimValue;
}
public void setClaimValue(String claimValue) {
this.claimValue = claimValue;
}
public String getTokenExpiryFrequency() {
return tokenExpiryFrequency;
}
public void setTokenExpiryFrequency(String tokenExpiryFrequency) {
this.tokenExpiryFrequency = tokenExpiryFrequency;
}
public String getTokenExpiryUnit() {
return tokenExpiryUnit;
}
public void setTokenExpiryUnit(String tokenExpiryUnit) {
this.tokenExpiryUnit = tokenExpiryUnit;
}
}
Main Class :
public class TokenApplication {
static ObjectMapper objectMapper = new ObjectMapper()
.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, true);
public static void main(String[] args) {
ProjectConfig projectConfig = loadConfiguration("application-stg.properties");
if (args.length > 0 && args[0].equals("PROD")) {
projectConfig = loadConfiguration("application-prod.properties");
}
try {
JWTTokenService jwtTokenService = new JWTTokenService();
System.out.println(jwtTokenService.getJwtToken(projectConfig).getAccessToken());
System.exit(JobStatus.SUCCESS.getCode());
} catch (Exception ex) {
System.exit(JobStatus.PROCESS_FAILED.getCode());
}
}
private static ProjectConfig loadConfiguration(String filePath) {
try (InputStream input = TokenApplication.class.getClassLoader().getResourceAsStream(filePath)) {
Properties props = new Properties();
props.load(input);
return objectMapper.convertValue(new HashMap(props), ProjectConfig.class);
} catch (Exception ex) {
throw new RuntimeException("Not able to load configuration" + ex.getMessage());
}
}
}
application-stg.properties
keyAlgorithm=RSA
keyPath=private-stage.der
subject=
issuer=
audience=
claimKey=
claimValue=true
tokenExpiryFrequency=DAY
tokenExpiryUnit=1
clientId=
clientSecret=
jwtTokenUrl=
Load RSA private key from a PEM encoded private key
The key is PEM encoded. You need to strip the PEM header and footer, then convert from Base64 back to DER/BER, and finally use Crypto++'s BERDecodePrivateKey
.
There's some reading on the subject at the Crypto++ wiki under Keys and Formats. Below is the code to perform the conversion (I don't believe Stack Overflow has a working example of it in Crypto++).
string RSA_PRIV_KEY =
"-----BEGIN RSA PRIVATE KEY-----\n"
"MIIBOgIBAAJBAK8Q+ToR4tWGshaKYRHKJ3ZmMUF6jjwCS/u1A8v1tFbQiVpBlxYB\n"
"paNcT2ENEXBGdmWqr8VwSl0NBIKyq4p0rhsCAQMCQHS1+3wL7I5ZzA8G62Exb6RE\n"
"INZRtCgBh/0jV91OeDnfQUc07SE6vs31J8m7qw/rxeB3E9h6oGi9IVRebVO+9zsC\n"
"IQDWb//KAzrSOo0P0yktnY57UF9Q3Y26rulWI6LqpsxZDwIhAND/cmlg7rUz34Pf\n"
"SmM61lJEmMEjKp8RB/xgghzmCeI1AiEAjvVVMVd8jCcItTdwyRO0UjWU4JOz0cnw\n"
"5BfB8cSIO18CIQCLVPbw60nOIpUClNxCJzmMLbsrbMcUtgVS6wFomVvsIwIhAK+A\n"
"YqT6WwsMW2On5l9di+RPzhDT1QdGyTI5eFNS+GxY\n"
"-----END RSA PRIVATE KEY-----";
static string HEADER = "-----BEGIN RSA PRIVATE KEY-----";
static string FOOTER = "-----END RSA PRIVATE KEY-----";
size_t pos1, pos2;
pos1 = RSA_PRIV_KEY.find(HEADER);
if(pos1 == string::npos)
throw runtime_error("PEM header not found");
pos2 = RSA_PRIV_KEY.find(FOOTER, pos1+1);
if(pos2 == string::npos)
throw runtime_error("PEM footer not found");
// Start position and length
pos1 = pos1 + HEADER.length();
pos2 = pos2 - pos1;
string keystr = RSA_PRIV_KEY.substr(pos1, pos2);
// Base64 decode, place in a ByteQueue
ByteQueue queue;
Base64Decoder decoder;
decoder.Attach(new Redirector(queue));
decoder.Put((const byte*)keystr.data(), keystr.length());
decoder.MessageEnd();
// Write to file for inspection
FileSink fs("decoded-key.der");
queue.CopyTo(fs);
fs.MessageEnd();
try
{
CryptoPP::RSA::PrivateKey rsaPrivate;
rsaPrivate.BERDecodePrivateKey(queue, false /*paramsPresent*/, queue.MaxRetrievable());
// BERDecodePrivateKey is a void function. Here's the only check
// we have regarding the DER bytes consumed.
ASSERT(queue.IsEmpty());
}
catch (const Exception& ex)
{
cerr << ex.what() << endl;
exit (1);
}
After loading the key, you can validate it with:
AutoSeededRandomPool prng;
bool valid = rsaPrivate.Validate(prng, 3);
if(!valid)
cerr << "RSA private key is not valid" << endl;
And print it with:
cout << "N: " << rsaPrivate.GetModulus() << endl << endl;
cout << "E: " << rsaPrivate.GetPublicExponent() << endl << endl;
cout << "D: " << rsaPrivate.GetPrivateExponent() << endl << endl;
If the key is password protected, then Crypto++ cannot decode it. The library lacks the support to perform the decryption. In this case, you can convert it to BER/DER using the following OpenSSL command. Then you can use the key material with Crypto++.
openssl pkcs8 -nocrypt -in rsa-key.pem -inform PEM -topk8 -outform DER -out rsa-key.der
The sample program wrote the key to file with this:
FileSink fs("decoded-key.der");
queue.CopyTo(fs);
fs.MessageEnd();
The CopyTo
leaves the bytes in the queue
for use later. You can dump the file with an ASN.1 tool, like Gutmann's dumpasn1
:
$ dumpasn1 decoded-key.der
0 314: SEQUENCE {
4 1: INTEGER 0
7 65: INTEGER
: 00 AF 10 F9 3A 11 E2 D5 86 B2 16 8A 61 11 CA 27
: 76 66 31 41 7A 8E 3C 02 4B FB B5 03 CB F5 B4 56
: D0 89 5A 41 97 16 01 A5 A3 5C 4F 61 0D 11 70 46
: 76 65 AA AF C5 70 4A 5D 0D 04 82 B2 AB 8A 74 AE
: 1B
74 1: INTEGER 3
77 64: INTEGER
: 74 B5 FB 7C 0B EC 8E 59 CC 0F 06 EB 61 31 6F A4
: 44 20 D6 51 B4 28 01 87 FD 23 57 DD 4E 78 39 DF
: 41 47 34 ED 21 3A BE CD F5 27 C9 BB AB 0F EB C5
: E0 77 13 D8 7A A0 68 BD 21 54 5E 6D 53 BE F7 3B
143 33: INTEGER
: 00 D6 6F FF CA 03 3A D2 3A 8D 0F D3 29 2D 9D 8E
: 7B 50 5F 50 DD 8D BA AE E9 56 23 A2 EA A6 CC 59
: 0F
178 33: INTEGER
: 00 D0 FF 72 69 60 EE B5 33 DF 83 DF 4A 63 3A D6
: 52 44 98 C1 23 2A 9F 11 07 FC 60 82 1C E6 09 E2
: 35
213 33: INTEGER
: 00 8E F5 55 31 57 7C 8C 27 08 B5 37 70 C9 13 B4
: 52 35 94 E0 93 B3 D1 C9 F0 E4 17 C1 F1 C4 88 3B
: 5F
248 33: INTEGER
: 00 8B 54 F6 F0 EB 49 CE 22 95 02 94 DC 42 27 39
: 8C 2D BB 2B 6C C7 14 B6 05 52 EB 01 68 99 5B EC
: 23
283 33: INTEGER
: 00 AF 80 62 A4 FA 5B 0B 0C 5B 63 A7 E6 5F 5D 8B
: E4 4F CE 10 D3 D5 07 46 C9 32 39 78 53 52 F8 6C
: 58
: }
0 warnings, 0 errors.
Related Topics
Is It Expensive to Use Try-Catch Blocks Even If an Exception Is Never Thrown
How to Create a Zip File in Java
How to Convert a Java 8 Intstream to a List
Java: Run a Function After a Specific Number of Seconds
How to Write Console Output to a Txt File
Generic Type Inference Not Working with Method Chaining
Painting the Slider Icon of Jslider
How to Derive Module Descriptor: Provider {Class X} Not in Module
Key Bindings VS. Key Listeners in Java
Recommendations on a Free Library to Be Used for Zipping Files
Why Does Java Implicitly (Without Cast) Convert a 'Long' to a 'Float'
How to Load a Resource from Web-Inf Directory of a Web Archive
How to Add and Remove Elements of Enumeration at Runtime in Java
How to Find the Index of an Element in an Array in Java
What Is the Main Difference Between Inheritance and Polymorphism