下面列出了怎么用java.security.spec.RSAPublicKeySpec的API类实例代码及写法,或者点击链接到github查看源代码。
private KeyPair loadRsaKeys(Path publicFile, Path privateFile)
throws GeneralSecurityException, ReflectiveOperationException,
IOException
{
KeyFactory factory = KeyFactory.getInstance("RSA");
// load public key
PublicKey publicKey;
try(ObjectInputStream in =
new ObjectInputStream(Files.newInputStream(publicFile)))
{
publicKey = factory.generatePublic(new RSAPublicKeySpec(
(BigInteger)in.readObject(), (BigInteger)in.readObject()));
}
// load private key
PrivateKey privateKey;
try(ObjectInputStream in =
new ObjectInputStream(Files.newInputStream(privateFile)))
{
privateKey = factory.generatePrivate(new RSAPrivateKeySpec(
(BigInteger)in.readObject(), (BigInteger)in.readObject()));
}
return new KeyPair(publicKey, privateKey);
}
/**
* generate key pair object from private key
*
* @param privateKey private key
* @return a key pair object
* @throws NoSuchAlgorithmException if can't create key factory by using
* RSA algorithm
* @throws InvalidKeySpecException if private key or public key is invalid
*/
private KeyPair createKeyPairFromPrivateKey(PrivateKey privateKey) throws
NoSuchAlgorithmException, InvalidKeySpecException
{
if(!(privateKey instanceof RSAPrivateCrtKey))
throw new IllegalArgumentException("Input private key is not a RSA private key");
KeyFactory kf = KeyFactory.getInstance("RSA");
//generate public key from private key
RSAPrivateCrtKey privk = (RSAPrivateCrtKey) privateKey;
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(privk.getModulus(),
privk.getPublicExponent());
PublicKey publicK = kf.generatePublic(publicKeySpec);
//create key pairs
return new KeyPair(publicK, privateKey);
}
PublicKey unmarshalKeyValue(Element kvtElem)
throws MarshalException
{
if (rsakf == null) {
try {
rsakf = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException
("unable to create RSA KeyFactory: " + e.getMessage());
}
}
Element modulusElem = DOMUtils.getFirstChildElement(kvtElem,
"Modulus");
modulus = new DOMCryptoBinary(modulusElem.getFirstChild());
Element exponentElem = DOMUtils.getNextSiblingElement(modulusElem,
"Exponent");
exponent = new DOMCryptoBinary(exponentElem.getFirstChild());
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus.getBigNum(),
exponent.getBigNum());
return generatePublicKey(rsakf, spec);
}
public static void main( final String[] args ) throws Exception {
final KeyPairGenerator kpGen = KeyPairGenerator.getInstance( "RSA" );
kpGen.initialize( KEY_SIZE_BITS );
final KeyPair kp = kpGen.generateKeyPair();
final PublicKey pubKey = kp.getPublic();
final PrivateKey privKey = kp.getPrivate();
if ( DEBUG ) {
System.out.println( pubKey .getAlgorithm() + " " + pubKey .getFormat() + " " + pubKey .getEncoded().length );
System.out.println( privKey.getAlgorithm() + " " + privKey.getFormat() + " " + privKey.getEncoded().length );
}
final KeyFactory kf = KeyFactory.getInstance( "RSA" );
final RSAPublicKeySpec pubKeySpec = kf.getKeySpec( pubKey , RSAPublicKeySpec .class );
final RSAPrivateKeySpec privKeySpec = kf.getKeySpec( privKey, RSAPrivateKeySpec.class );
if ( DEBUG ) {
System.out.println( pubKeySpec .getModulus() + " " + pubKeySpec .getPublicExponent() );
System.out.println( privKeySpec.getModulus() + " " + privKeySpec.getPrivateExponent() );
}
saveKey( pubKeySpec .getModulus(), pubKeySpec .getPublicExponent (), "w:/pubkey.rsa" );
saveKey( privKeySpec.getModulus(), privKeySpec.getPrivateExponent(), "w:/privkey.rsa" );
}
private PEM decode_PKCS_1_Public(String encodedKey) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
byte[] bytes = getKeyBytes(encodedKey, PKCS_1_PUBLIC_KEY_PREFIX, PKCS_1_PUBLIC_KEY_SUFFIX);
DerValue[] sequence = new DerInputStream(bytes).getSequence();
// DER Encoded PKCS#1 structure
// ------------------------------------------------------
// RSAPublicKey ::= SEQUENCE {
// modulus INTEGER, -- n
// publicExponent INTEGER -- e
// }
if (sequence.length != 2 || !sequence[0].tag.is(Tag.Integer) || !sequence[1].tag.is(Tag.Integer)) {
// Expect the following format : [ Integer | Integer ]
throw new InvalidKeyException("Could not build this PKCS#1 public key. Expecting values in the DER encoded sequence in the following format [ Integer | Integer ]");
}
BigInteger modulus = sequence[0].getBigInteger();
BigInteger publicExponent = sequence[1].getBigInteger();
return new PEM(KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, publicExponent)));
}
PublicKey unmarshalKeyValue(Element kvtElem)
throws MarshalException
{
if (rsakf == null) {
try {
rsakf = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException
("unable to create RSA KeyFactory: " + e.getMessage());
}
}
Element modulusElem = DOMUtils.getFirstChildElement(kvtElem,
"Modulus");
modulus = new DOMCryptoBinary(modulusElem.getFirstChild());
Element exponentElem = DOMUtils.getNextSiblingElement(modulusElem,
"Exponent");
exponent = new DOMCryptoBinary(exponentElem.getFirstChild());
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus.getBigNum(),
exponent.getBigNum());
return generatePublicKey(rsakf, spec);
}
PublicKey unmarshalKeyValue(Element kvtElem)
throws MarshalException
{
if (rsakf == null) {
try {
rsakf = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException
("unable to create RSA KeyFactory: " + e.getMessage());
}
}
Element modulusElem = DOMUtils.getFirstChildElement(kvtElem,
"Modulus");
modulus = new DOMCryptoBinary(modulusElem.getFirstChild());
Element exponentElem = DOMUtils.getNextSiblingElement(modulusElem,
"Exponent");
exponent = new DOMCryptoBinary(exponentElem.getFirstChild());
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus.getBigNum(),
exponent.getBigNum());
return generatePublicKey(rsakf, spec);
}
/**
* from <type><space><base64data><space><comment> to public key
*/
private static PublicKey toPublicKey(String sshPublicKey)
throws NoSuchAlgorithmException, InvalidKeySpecException {
String[] line = sshPublicKey.trim().split(" ", 3);
String type = line[0];
String content = line[1];
ByteBuffer buf = ByteBuffer.wrap(Base64.getDecoder().decode(content));
// format of decoded content is: <type><keyparams>
// where type and each param is a DER string
String decodedType = new String(readDERString(buf));
if (!decodedType.equals(type)) {
throw new IllegalArgumentException("expected " + type + ", got " + decodedType);
}
if (type.equals("ssh-rsa")) {
BigInteger e = new BigInteger(readDERString(buf));
BigInteger y = new BigInteger(readDERString(buf));
return KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(y, e));
}
throw new InvalidKeySpecException("Unknown key type '" + type + "'");
}
PublicKey unmarshalKeyValue(Element kvtElem)
throws MarshalException
{
if (rsakf == null) {
try {
rsakf = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException
("unable to create RSA KeyFactory: " + e.getMessage());
}
}
Element modulusElem = DOMUtils.getFirstChildElement(kvtElem,
"Modulus");
modulus = new DOMCryptoBinary(modulusElem.getFirstChild());
Element exponentElem = DOMUtils.getNextSiblingElement(modulusElem,
"Exponent");
exponent = new DOMCryptoBinary(exponentElem.getFirstChild());
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus.getBigNum(),
exponent.getBigNum());
return generatePublicKey(rsakf, spec);
}
public static KeyPair convertFromPaillier(final PaillierKeyPair paillierKeyPair)
throws InvalidKeySpecException, NoSuchAlgorithmException {
// Get keys
final PaillierPrivateKey paillierPrivateKey = paillierKeyPair.getPrivateKey();
final PaillierPublicKey paillierPublicKey = paillierKeyPair.getPublicKey();
// Get fields
final BigInteger n = paillierPublicKey.getN(); // treat as 'N'
final BigInteger e = paillierPublicKey.getG(); // treat as 'e'
final BigInteger d = paillierPrivateKey.getLambda(); // treat as 'd'
// Represent them as RSA keys
final RSAPrivateKeySpec privKeySpec = new RSAPrivateKeySpec(n, d);
final RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(n, e);
// Convert to key pair
final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
final PublicKey rsaPublic = keyFactory.generatePublic(pubKeySpec);
final PrivateKey rsaPrivate = keyFactory.generatePrivate(privKeySpec);
return new KeyPair(rsaPublic, rsaPrivate);
}
PublicKey unmarshalKeyValue(Element kvtElem)
throws MarshalException
{
if (rsakf == null) {
try {
rsakf = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException
("unable to create RSA KeyFactory: " + e.getMessage());
}
}
Element modulusElem = DOMUtils.getFirstChildElement(kvtElem,
"Modulus");
modulus = new DOMCryptoBinary(modulusElem.getFirstChild());
Element exponentElem = DOMUtils.getNextSiblingElement(modulusElem,
"Exponent");
exponent = new DOMCryptoBinary(exponentElem.getFirstChild());
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus.getBigNum(),
exponent.getBigNum());
return generatePublicKey(rsakf, spec);
}
/**
* Decode a JWK(S) encoded public key string to an RSA PublicKey
* @param jwksValue - JWKS string value
* @return RSAPublicKey from RSAPublicKeySpec
*/
public static RSAPublicKey decodeJWKSPublicKey(String jwksValue) throws Exception {
JsonObject jwks = Json.createReader(new StringReader(jwksValue)).readObject();
JsonArray keys = jwks.getJsonArray("keys");
JsonObject jwk;
if(keys != null) {
jwk = keys.getJsonObject(0);
}
else {
jwk = jwks;
}
String e = jwk.getString("e");
String n = jwk.getString("n");
byte[] ebytes = Base64.getUrlDecoder().decode(e);
BigInteger publicExponent = new BigInteger(1, ebytes);
byte[] nbytes = Base64.getUrlDecoder().decode(n);
BigInteger modulus = new BigInteger(1, nbytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(modulus, publicExponent);
return (RSAPublicKey)kf.generatePublic(rsaPublicKeySpec);
}
@Test
public void generatePublicKeyFromJWKs() throws Exception {
String jsonJwk = TokenUtils.readResource("/signer-keyset4k.jwk");
System.out.printf("jwk: %s\n", jsonJwk);
JsonObject jwks = Json.createReader(new StringReader(jsonJwk)).readObject();
JsonArray keys = jwks.getJsonArray("keys");
JsonObject jwk = keys.getJsonObject(0);
String e = jwk.getString("e");
String n = jwk.getString("n");
byte[] ebytes = Base64.getUrlDecoder().decode(e);
BigInteger publicExponent = new BigInteger(1, ebytes);
byte[] nbytes = Base64.getUrlDecoder().decode(n);
BigInteger modulus = new BigInteger(1, nbytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(modulus, publicExponent);
PublicKey publicKey = kf.generatePublic(rsaPublicKeySpec);
System.out.printf("publicKey=%s\n", publicKey);
String pem = new String(Base64.getEncoder().encode(publicKey.getEncoded()));
System.out.printf("pem: %s\n", pem);
}
/**
* Get the public key that is used to verify the JWT from the user service. We assume the key is
* an RSA key.
*
* @throws NoSuchAlgorithmException
*/
private PublicKey getPublicKey()
throws Base64Exception, InvalidKeySpecException, NoSuchAlgorithmException {
String url =
"https://" + libertyHostname + ":" + libertySslPort + "/jwt/ibm/api/jwtUserBuilder/jwk";
Response response = processRequest(url, "GET", null, null);
assertEquals(
"HTTP response code should have been " + Status.OK.getStatusCode() + ".",
Status.OK.getStatusCode(),
response.getStatus());
// Liberty returns the keys in an array. We'll grab the first one (there
// should only be one).
JsonObject jwkResponse = toJsonObj(response.readEntity(String.class));
JsonArray jwkArray = jwkResponse.getJsonArray("keys");
JsonObject jwk = jwkArray.getJsonObject(0);
BigInteger modulus = new BigInteger(1, Base64Utility.decode(jwk.getString("n"), true));
BigInteger publicExponent = new BigInteger(1, Base64Utility.decode(jwk.getString("e"), true));
return KeyFactory.getInstance("RSA")
.generatePublic(new RSAPublicKeySpec(modulus, publicExponent));
}
public KeyPair getKeyPair(String alias, char[] password) {
try {
synchronized (lock) {
if (store == null) {
synchronized (lock) {
store = KeyStore.getInstance("jks");
store.load(resource.getInputStream(), this.password);
}
}
}
RSAPrivateCrtKey key = (RSAPrivateCrtKey) store.getKey(alias, password);
RSAPublicKeySpec spec = new RSAPublicKeySpec(key.getModulus(), key.getPublicExponent());
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(spec);
return new KeyPair(publicKey, key);
}
catch (Exception e) {
throw new IllegalStateException("Cannot load keys from store: " + resource, e);
}
}
@Override
public void generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException {
// https://github.com/bcgit/bc-java/blob/53d17ef99e30c6bd49e6eec9235e3eefca6a222d/pkix/src/test/java/org/bouncycastle/cert/test/CertTest.java
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(
"b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), new BigInteger("11", 16));
RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec(new BigInteger(
"b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), new BigInteger("11", 16), new BigInteger(
"9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16), new BigInteger(
"c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16), new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16), new BigInteger(
"b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16), new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16), new BigInteger(
"b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16));
KeyFactory fact = KeyFactory.getInstance("RSA", "BC");
setPrivateKey(fact.generatePrivate(privKeySpec));
setPublicKey(fact.generatePublic(pubKeySpec));
}
public static String encrypt(byte[] keyBytes, String plainText)
throws Exception {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = factory.generatePrivate(spec);
Cipher cipher = Cipher.getInstance("RSA");
try {
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
} catch (InvalidKeyException e) {
//For IBM JDK, 原因请看解密方法中的说明
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(rsaPrivateKey.getModulus(), rsaPrivateKey.getPrivateExponent());
Key fakePublicKey = KeyFactory.getInstance("RSA").generatePublic(publicKeySpec);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, fakePublicKey);
}
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
String encryptedString = Base64.byteArrayToBase64(encryptedBytes);
return encryptedString;
}
/**
* 从KeyStore获取公钥
* @param location
* @param alias
* @param storeType
* @param storePass
* @param keyPass
* @return
*/
public static PublicKey loadPublicKeyFromKeyStore(String location, String alias, String storeType, String storePass, String keyPass) {
try {
storeType = null == storeType ? KeyStore.getDefaultType() : storeType;
keyPass = keyPass == null ? storePass : keyPass;
KeyStore keyStore = KeyStore.getInstance(storeType);
InputStream is = new FileInputStream(location);
keyStore.load(is, storePass.toCharArray());
RSAPrivateCrtKey key = (RSAPrivateCrtKey) keyStore.getKey(alias, keyPass.toCharArray());
RSAPublicKeySpec spec = new RSAPublicKeySpec(key.getModulus(),
key.getPublicExponent());
PublicKey publicKey = KeyFactory.getInstance(KEY_ALGORITHM).generatePublic(spec);
return publicKey;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private PublicKey decodePublicKey() throws Exception {
InputStream stream = new ClassPathResource("/keys/sftp_rsa.pub").getInputStream();
byte[] decodeBuffer = Base64.decodeBase64(StreamUtils.copyToByteArray(stream));
ByteBuffer bb = ByteBuffer.wrap(decodeBuffer);
int len = bb.getInt();
byte[] type = new byte[len];
bb.get(type);
if ("ssh-rsa".equals(new String(type))) {
BigInteger e = decodeBigInt(bb);
BigInteger m = decodeBigInt(bb);
RSAPublicKeySpec spec = new RSAPublicKeySpec(m, e);
return KeyFactory.getInstance("RSA").generatePublic(spec);
}
else {
throw new IllegalArgumentException("Only supports RSA");
}
}
private PublicKey decodePublicKey() throws Exception {
InputStream stream = new ClassPathResource("/keys/sftp_rsa.pub").getInputStream();
byte[] decodeBuffer = Base64.decodeBase64(StreamUtils.copyToByteArray(stream));
ByteBuffer bb = ByteBuffer.wrap(decodeBuffer);
int len = bb.getInt();
byte[] type = new byte[len];
bb.get(type);
if ("ssh-rsa".equals(new String(type))) {
BigInteger e = decodeBigInt(bb);
BigInteger m = decodeBigInt(bb);
RSAPublicKeySpec spec = new RSAPublicKeySpec(m, e);
return KeyFactory.getInstance("RSA").generatePublic(spec);
}
else {
throw new IllegalArgumentException("Only supports RSA");
}
}
/**
* Tests legacy signatures. In this context we use the term legacy signatures for signatures that
* are not conforming to the PKCS #1 standard, but are sometimes generated by buggy signers. So
* far this test considers both accepting and rejecting such signatures as valid behavior.
*
* <p>Currently we check for just one type of legacy signatures: i.e., a missing NULL parameter in
* the ASN encoding of the hash. BouncyCastle and the SunJCE accept this signature, Conscrypt does
* not.
*
* <p>Some references that support accepting this signature:
* https://codereview.chromium.org/1690123002/
* https://groups.google.com/a/chromium.org/forum/#!topic/chromium-reviews/Jo5S7HtEABI claims that
* 7% of the responses in the Online Certificate Status Protocol (OCSP) miss the NULL parameter
*/
@Test
public void testLegacySignatures() throws Exception {
RSAPublicKeySpec key = RSA_KEY1;
String algorithm = ALGORITHM_KEY1;
byte[] message = "Test".getBytes("UTF-8");
Signature verifier = Signature.getInstance(algorithm);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pub = kf.generatePublic(key);
for (String signature : LEGACY_SIGNATURES_KEY1) {
byte[] signatureBytes = TestUtil.hexToBytes(signature);
verifier.initVerify(pub);
verifier.update(message);
boolean verified = false;
try {
verified = verifier.verify(signatureBytes);
} catch (SignatureException ex) {
verified = false;
}
if (verified) {
System.out.println("Verfied legacy signature:" + signature);
} else {
System.out.println("Rejected legacy signature:" + signature);
}
}
}
@Bean
KeyPair keyPair() {
try {
String privateExponent = "3851612021791312596791631935569878540203393691253311342052463788814433805390794604753109719790052408607029530149004451377846406736413270923596916756321977922303381344613407820854322190592787335193581632323728135479679928871596911841005827348430783250026013354350760878678723915119966019947072651782000702927096735228356171563532131162414366310012554312756036441054404004920678199077822575051043273088621405687950081861819700809912238863867947415641838115425624808671834312114785499017269379478439158796130804789241476050832773822038351367878951389438751088021113551495469440016698505614123035099067172660197922333993";
String modulus = "18044398961479537755088511127417480155072543594514852056908450877656126120801808993616738273349107491806340290040410660515399239279742407357192875363433659810851147557504389760192273458065587503508596714389889971758652047927503525007076910925306186421971180013159326306810174367375596043267660331677530921991343349336096643043840224352451615452251387611820750171352353189973315443889352557807329336576421211370350554195530374360110583327093711721857129170040527236951522127488980970085401773781530555922385755722534685479501240842392531455355164896023070459024737908929308707435474197069199421373363801477026083786683";
String exponent = "65537";
RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(exponent));
RSAPrivateKeySpec privateSpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(privateExponent));
KeyFactory factory = KeyFactory.getInstance("RSA");
return new KeyPair(factory.generatePublic(publicSpec), factory.generatePrivate(privateSpec));
} catch ( Exception e ) {
throw new IllegalArgumentException(e);
}
}
/**
* 使用模和指数生成RSA公钥
* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
* /None/NoPadding】
*
* @param modulus 模
* @param exponent 指数
* @return
*/
public static RSAPublicKey getPublicKey(String modulus, String exponent) {
try {
final BigInteger b1 = new BigInteger(modulus);
final BigInteger b2 = new BigInteger(exponent);
final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
final RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (Exception e) {
return null;
}
}
private RSAServerKeyExchangeMessage(HandshakeContext handshakeContext,
X509Possession x509Possession,
EphemeralRSAPossession rsaPossession) throws IOException {
super(handshakeContext);
// This happens in server side only.
ServerHandshakeContext shc =
(ServerHandshakeContext)handshakeContext;
RSAPublicKey publicKey = rsaPossession.popPublicKey;
RSAPublicKeySpec spec = JsseJce.getRSAPublicKeySpec(publicKey);
this.modulus = Utilities.toByteArray(spec.getModulus());
this.exponent = Utilities.toByteArray(spec.getPublicExponent());
byte[] signature = null;
try {
Signature signer = RSASignature.getInstance();
signer.initSign(x509Possession.popPrivateKey,
shc.sslContext.getSecureRandom());
updateSignature(signer,
shc.clientHelloRandom.randomBytes,
shc.serverHelloRandom.randomBytes);
signature = signer.sign();
} catch (NoSuchAlgorithmException |
InvalidKeyException | SignatureException ex) {
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
"Failed to sign ephemeral RSA parameters", ex);
}
this.paramsSignature = signature;
}
/**
* Tests an RSA signature implementation with a number of vectors. The test assumes that the first
* test vector is valid, but everything else is invalid. Many of the test vectors are derived by
* signing modified ASN encodings. Hence accepting an invalid signature does not mean by itself
* that the implementation can be broken, but often points to a bigger problem. The test expects
* that verifying an invalid signature either leads to a return value False or will result in a
* SignatureException. Verifying an RSA signature should not result in an RuntimeException, so
* that reasonably implementated applications can be expected to catch and treat invalid
* signatures appropriately. While RuntimeExceptions may not be exploitable, they often indicate
* an oversight in the implementation of the provider.
* https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html
*/
private void testVectors(RSAPublicKeySpec key, String algorithm, String[] testvectors)
throws Exception {
byte[] message = "Test".getBytes("UTF-8");
Signature verifier = Signature.getInstance(algorithm);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pub = kf.generatePublic(key);
int errors = 0;
boolean first = true;
for (String signature : testvectors) {
byte[] signatureBytes = TestUtil.hexToBytes(signature);
verifier.initVerify(pub);
verifier.update(message);
boolean verified = false;
try {
verified = verifier.verify(signatureBytes);
} catch (SignatureException ex) {
// verify can throw SignatureExceptions if the signature is malformed.
}
if (first && !verified) {
System.out.println("Valid signature not verified:" + signature);
errors++;
} else if (!first && verified) {
System.out.println("Incorrect signature verified:" + signature);
errors++;
}
first = false;
}
assertEquals(0, errors);
}
public static void main(String[] args) throws Exception {
boolean result = true;
Provider p = Security.getProvider("SunJCE");
System.out.println("Testing provider " + p.getName() + "...");
// Test#1: make sure Cipher.getMaxAllowedKeyLength returns the
// correct value
if (Cipher.getMaxAllowedKeyLength("RSA") != Integer.MAX_VALUE) {
result = false;
System.out.println("Test#1 failed");
}
// Test#2: try initializing RSA cipher with 4096 key
String algo = "RSA";
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec
(new BigInteger(MODULUS4096), new BigInteger(PUB4096));
KeyFactory kf = KeyFactory.getInstance(algo);
RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(pubKeySpec);
Cipher c = Cipher.getInstance(algo + "/ECB/NoPadding", p);
try {
c.init(Cipher.ENCRYPT_MODE, pubKey);
} catch (InvalidKeyException ike) {
result = false;
System.out.println("Test#2 failed");
ike.printStackTrace();
}
if (result) {
System.out.println("All tests passed!");
} else {
throw new Exception("One or more test failed!");
}
}
public static void main(String[] args) throws Exception {
boolean result = true;
Provider p = Security.getProvider("SunJCE");
System.out.println("Testing provider " + p.getName() + "...");
// Test#1: make sure Cipher.getMaxAllowedKeyLength returns the
// correct value
if (Cipher.getMaxAllowedKeyLength("RSA") != Integer.MAX_VALUE) {
result = false;
System.out.println("Test#1 failed");
}
// Test#2: try initializing RSA cipher with 4096 key
String algo = "RSA";
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec
(new BigInteger(MODULUS4096), new BigInteger(PUB4096));
KeyFactory kf = KeyFactory.getInstance(algo);
RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(pubKeySpec);
Cipher c = Cipher.getInstance(algo + "/ECB/NoPadding", p);
try {
c.init(Cipher.ENCRYPT_MODE, pubKey);
} catch (InvalidKeyException ike) {
result = false;
System.out.println("Test#2 failed");
ike.printStackTrace();
}
if (result) {
System.out.println("All tests passed!");
} else {
throw new Exception("One or more test failed!");
}
}
private PublicKey createRSAPublicKey() {
BigInteger modulus = new BigInteger(1, Base64Url.decode(jwk.getOtherClaims().get(RSAPublicJWK.MODULUS).toString()));
BigInteger publicExponent = new BigInteger(1, Base64Url.decode(jwk.getOtherClaims().get(RSAPublicJWK.PUBLIC_EXPONENT).toString()));
try {
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(new RSAPublicKeySpec(modulus, publicExponent));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static PublicKey pubKeyFromModulusAndExponent(String modulus_b64, String exponent_b64)
throws NoSuchAlgorithmException,
InvalidKeySpecException {
modulus_b64 = unUrlSafe(modulus_b64)
.replaceAll("\\\\n","")
.replaceAll("[\\r|\\n| ]","");
exponent_b64 = unUrlSafe(exponent_b64)
.replaceAll("\\\\n","")
.replaceAll("[\\r|\\n| ]","");
byte[] decodedModulus = Base64.decodeBase64(modulus_b64);
byte[] decodedExponent = Base64.decodeBase64(exponent_b64);
String modulus_hex = Hex.encodeHexString( decodedModulus );
String exponent_hex = Hex.encodeHexString( decodedExponent );
BigInteger modulus = new BigInteger(modulus_hex, 16);
BigInteger publicExponent = new BigInteger(exponent_hex, 16);
PublicKey publicKey = KeyFactory
.getInstance("RSA")
.generatePublic(new RSAPublicKeySpec(modulus, publicExponent));
return publicKey;
}
public static RSAPublicKey generateRSAPublicKey(RSAPublicKeySpec keySpec)
throws InvalidKeySpecException {
Args.notNull(keySpec, "keySpec");
KeyFactory kf = getKeyFactory("RSA");
synchronized (kf) {
return (RSAPublicKey) kf.generatePublic(keySpec);
}
}