下面列出了怎么用java.security.interfaces.RSAPublicKey的API类实例代码及写法,或者点击链接到github查看源代码。
public static String decrypt(PublicKey publicKey, String cipherText)
throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
try {
cipher.init(Cipher.DECRYPT_MODE, publicKey);
} catch (InvalidKeyException e) {
// 因为 IBM JDK 不支持私钥加密, 公钥解密, 所以要反转公私钥
// 也就是说对于解密, 可以通过公钥的参数伪造一个私钥对象欺骗 IBM JDK
RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
RSAPrivateKeySpec spec = new RSAPrivateKeySpec(rsaPublicKey.getModulus(), rsaPublicKey.getPublicExponent());
Key fakePrivateKey = KeyFactory.getInstance("RSA").generatePrivate(spec);
cipher = Cipher.getInstance("RSA"); //It is a stateful object. so we need to get new one.
cipher.init(Cipher.DECRYPT_MODE, fakePrivateKey);
}
if (cipherText == null || cipherText.length() == 0) {
return cipherText;
}
byte[] cipherBytes = Base64.base64ToByteArray(cipherText);
byte[] plainBytes = cipher.doFinal(cipherBytes);
return new String(plainBytes);
}
private RSAPublicKey parseRSAPublicKey(String pem) throws ServletException {
String fullPem = PEM_HEADER + pem + PEM_FOOTER;
try {
CertificateFactory fact = CertificateFactory.getInstance("X.509");
ByteArrayInputStream is = new ByteArrayInputStream(fullPem.getBytes("UTF8"));
X509Certificate cer = (X509Certificate) fact.generateCertificate(is);
return (RSAPublicKey) cer.getPublicKey();
} catch (CertificateException ce) {
String message;
if (pem.startsWith(PEM_HEADER)) {
message = "CertificateException - be sure not to include PEM header "
+ "and footer in the PEM configuration element.";
} else {
message = "CertificateException - PEM may be corrupt";
}
throw new ServletException(message, ce);
} catch (UnsupportedEncodingException uee) {
throw new ServletException(uee);
}
}
/**
* Builds the JSON response of JWKS.
*
* @param publicKey Public Key which should be included in the jwks response.
* @param certificate Certificate which should be in the jwks response.
* @return JSON JWKS response.
* @throws CertificateException
* @throws NoSuchAlgorithmException
* @throws ParseException
*/
public static String buildResponse(PublicKey publicKey, Certificate certificate) throws CertificateException,
NoSuchAlgorithmException, ParseException {
JSONArray jwksArray = new JSONArray();
JSONObject jwksJson = new JSONObject();
if (publicKey instanceof RSAPublicKey) {
RSAKey.Builder jwk = new RSAKey.Builder((RSAPublicKey) publicKey);
jwk.keyID(CertificateUtils.getThumbPrint(certificate));
jwk.algorithm(JWSAlgorithm.RS256);
jwk.keyUse(KeyUse.parse("sig"));
jwksArray.put(jwk.build().toJSONObject());
jwksJson.put("keys", jwksArray);
log.debug(jwksJson.toString());
}
return jwksJson.toString();
}
@SuppressWarnings("unchecked")
private OpenIdMetadataKey findKey(String keyId) {
if (!keyCache.containsKey(keyId)) {
LOGGER.warn("findKey: keyId " + keyId + " doesn't exist.");
return null;
}
try {
Jwk jwk = keyCache.get(keyId);
OpenIdMetadataKey key = new OpenIdMetadataKey();
key.key = (RSAPublicKey) jwk.getPublicKey();
key.endorsements = (List<String>) jwk.getAdditionalAttributes().get("endorsements");
key.certificateChain = jwk.getCertificateChain();
return key;
} catch (JwkException e) {
String errorDescription = String.format("Failed to load keys: %s", e.getMessage());
LOGGER.warn(errorDescription);
}
return null;
}
public static String createToken(KeyPair keyPair, String issuer, Date issuedAt, Date expiresAt, String level)
throws NoSuchAlgorithmException,
NoSuchProviderException,
DynamicLogLevelException {
Algorithm rsa256 = Algorithm.RSA256((RSAPublicKey) keyPair.getPublic(), (RSAPrivateKey) keyPair.getPrivate());
if (ALLOWED_DYNAMIC_LOGLEVELS.contains(level)) {
return JWT.create().withIssuer(issuer).//
withIssuedAt(issuedAt). //
withExpiresAt(expiresAt).//
withClaim("level", level).sign(rsa256);
} else {
throw new DynamicLogLevelException("Dynamic Log-Level [" + level +
"] provided in header is not valid. Allowed Values are " +
ALLOWED_DYNAMIC_LOGLEVELS.toString());
}
}
public static String rsaEncode(String data, String publicKey) {
try {
//将字符串形式解析成类
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);
return Base64.encodeBase64URLSafeString(cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)));
} catch (Exception e) {
logger.warn(e.getMessage());
return null;
}
}
@Test
public void rsaAuthRefreshRequestBuildTest() throws Exception {
String p12Password = "123456";
String signAlg = "SHA256WITHRSA";
String refreshToken = "xxxxx";
KeyStore keyStore = CertUtil.readKeyStore("d:/cert/p12/rsa/client/client.p12", p12Password);
PrivateKey privateKey = CertUtil.getPrivateKey(keyStore, p12Password, null);
PublicKey publicKey = CertUtil.getPublicKey(keyStore, null);
RSAPublicKey serverPublicKey = (RSAPublicKey) CertUtil.readPublicKeyPem("d:/cert/p12/rsa/server/server_pub.pem");
ISign rsaSign = new RsaSign((RSAPublicKey) publicKey, (RSAPrivateKey) privateKey, signAlg);
AuthRefreshRequestDTO authRefreshRequestDTO = newAuthRefreshRequest(rsaSign, refreshToken);
byte[] data = JSONUtil.toJsonBytes(authRefreshRequestDTO);
EncodeRequestDTO encodeRequestDTO = new EncodeRequestDTO();
RSA rsa = new RSA();
encodeRequestDTO.setData(Base64.encodeBase64URLSafeString(rsa.encrypt(data, serverPublicKey)));
System.out.println(JSONUtil.toJsonString(encodeRequestDTO));
}
@Override
public boolean verifyToken(JWT token, RSAPublicKey publicKey)
throws TokenServiceException {
boolean rc;
PublicKey key;
try {
if (publicKey == null) {
key = ks.getSigningKeystore().getCertificate(getSigningKeyAlias()).getPublicKey();
}
else {
key = publicKey;
}
JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) key);
// TODO: interrogate the token for issuer claim in order to determine the public key to use for verification
// consider jwk for specifying the key too
rc = token.verify(verifier);
} catch (KeyStoreException | KeystoreServiceException e) {
throw new TokenServiceException("Cannot verify token.", e);
}
return rc;
}
/**
*
* 生成KeyPair
* @return
* @throws Exception
*/
public static Map<String, Object> generateKeyPair() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(KEYSIZE);
KeyPair keyPair = keyPairGen.generateKeyPair();
// 公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
BigInteger modules = privateKey.getModulus();
Map<String, Object> keys = new HashMap<String, Object>(3);
keys.put(PUBLIC_KEY, publicKey);
keys.put(PRIVATE_KEY, privateKey);
keys.put(MODULES, modules);
return keys;
}
@Test
public void rsaAuthRequestBuildTest() throws Exception {
String apiAccount = "dushitaoyuan-rsa";
String p12Password = "123456";
String signAlg = "SHA256WITHRSA";
KeyStore keyStore = CertUtil.readKeyStore("d:/cert/p12/rsa/client/client.p12", p12Password);
RSAPrivateKey privateKey = (RSAPrivateKey) CertUtil.getPrivateKey(keyStore, p12Password, null);
RSAPublicKey publicKey = (RSAPublicKey) CertUtil.getPublicKey(keyStore, null);
RSAPublicKey serverPublicKey = (RSAPublicKey) CertUtil.readPublicKeyPem("d:/cert/p12/rsa/server/server_pub.pem");
ISign rsaSign = new RsaSign(publicKey, privateKey, signAlg);
AuthRequestDTO authRequestDTO = newAuthRequest(rsaSign, apiAccount);
byte[] data = JSONUtil.toJsonBytes(authRequestDTO);
EncodeRequestDTO encodeRequestDTO = new EncodeRequestDTO();
RSA rsa = new RSA();
encodeRequestDTO.setData(Base64.encodeBase64URLSafeString(rsa.encrypt(data, serverPublicKey)));
System.out.println(JSONUtil.toJsonString(encodeRequestDTO));
}
@Override
public SSLPossession createPossession(HandshakeContext context) {
try {
EphemeralKeyManager ekm =
context.sslContext.getEphemeralKeyManager();
KeyPair kp = ekm.getRSAKeyPair(
true, context.sslContext.getSecureRandom());
if (kp != null) {
return new EphemeralRSAPossession(
kp.getPrivate(), (RSAPublicKey)kp.getPublic());
} else {
// Could not generate the ephemeral key, ignore.
return null;
}
} catch (RuntimeException rte) {
// Could not determine keylength, ignore.
return null;
}
}
public static void main(String[] args) throws Exception {
String FILE = "newsize7-ks";
new File(FILE).delete();
sun.security.tools.keytool.Main.main(("-debug -genkeypair -keystore " +
FILE +
" -alias a -dname cn=c -storepass changeit" +
" -keypass changeit -keyalg rsa").split(" "));
KeyStore ks = KeyStore.getInstance("JKS");
try (FileInputStream fin = new FileInputStream(FILE)) {
ks.load(fin, "changeit".toCharArray());
}
Files.delete(Paths.get(FILE));
RSAPublicKey r = (RSAPublicKey)ks.getCertificate("a").getPublicKey();
if (r.getModulus().bitLength() != 2048) {
throw new Exception("Bad keysize");
}
X509Certificate x = (X509Certificate)ks.getCertificate("a");
if (!x.getSigAlgName().equals("SHA256withRSA")) {
throw new Exception("Bad sigalg");
}
}
private static String[] commonKey(int size) throws NoSuchAlgorithmException {
String [] keys = new String[2];
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
keyPairGenerator.initialize(size);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
keys[0] = Base64.byteArrayToBase64(rsaPrivateKey.getEncoded());
// 公钥
keys[1] = Base64.byteArrayToBase64(rsaPublicKey.getEncoded());
return keys;
}
/**
*
* @param kpair test key pair
* @param pubExponent expected public exponent.
* @return true if test passed. false if test failed.
*/
private static boolean specTest(KeyPair kpair, BigInteger pubExponent) {
boolean passed = true;
RSAPrivateKey priv = (RSAPrivateKey) kpair.getPrivate();
RSAPublicKey pub = (RSAPublicKey) kpair.getPublic();
// test the getModulus method
if ((priv instanceof RSAKey) && (pub instanceof RSAKey)) {
if (!priv.getModulus().equals(pub.getModulus())) {
System.out.println("priv.getModulus() = " + priv.getModulus());
System.out.println("pub.getModulus() = " + pub.getModulus());
passed = false;
}
if (!pubExponent.equals(pub.getPublicExponent())) {
System.out.println("pubExponent = " + pubExponent);
System.out.println("pub.getPublicExponent() = "
+ pub.getPublicExponent());
passed = false;
}
}
return passed;
}
public static <T extends Key> void assertKeyEquals(String message, T expected, T actual) {
if (expected == actual) {
return;
}
assertEquals(message + "[algorithm]", expected.getAlgorithm(), actual.getAlgorithm());
if (expected instanceof RSAPublicKey) {
assertRSAPublicKeyEquals(message, RSAPublicKey.class.cast(expected), RSAPublicKey.class.cast(actual));
} else if (expected instanceof DSAPublicKey) {
assertDSAPublicKeyEquals(message, DSAPublicKey.class.cast(expected), DSAPublicKey.class.cast(actual));
} else if (expected instanceof ECPublicKey) {
assertECPublicKeyEquals(message, ECPublicKey.class.cast(expected), ECPublicKey.class.cast(actual));
} else if (expected instanceof RSAPrivateKey) {
assertRSAPrivateKeyEquals(message, RSAPrivateKey.class.cast(expected), RSAPrivateKey.class.cast(actual));
} else if (expected instanceof ECPrivateKey) {
assertECPrivateKeyEquals(message, ECPrivateKey.class.cast(expected), ECPrivateKey.class.cast(actual));
}
assertArrayEquals(message + "[encdoded-data]", expected.getEncoded(), actual.getEncoded());
}
@Test(expectedExceptions = { ParseException.class }, description = "Illustrate validation of exp that has just expired")
public void testNimbusFailJustExpired() throws Exception {
HashMap<String, Long> timeClaims = new HashMap<>();
// Set exp to 61 seconds in past
long exp = TokenUtils.currentTimeInSecs() - 61;
timeClaims.put(Claims.exp.name(), exp);
String token = TokenUtils.generateTokenString("/Token1.json", null, timeClaims);
RSAPublicKey publicKey = (RSAPublicKey) TokenUtils.readPublicKey("/publicKey.pem");
JWTAuthContextInfo contextInfo = new JWTAuthContextInfo(publicKey, "https://server.example.com");
contextInfo.setExpGracePeriodSecs(60);
JsonWebToken jwt = validateToken(token, contextInfo);
}
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!");
}
}
/**
* Constructor.
*
* Generates a new RsaKey with given KeyPair. The given provider is used for algorithm implementation.
* The keyPair must be an RSAKey.
* @param kid
* @param keyPair
* @param provider Java security provider
*/
public RsaKey(String kid, KeyPair keyPair, Provider provider) {
if (Strings.isNullOrWhiteSpace(kid)) {
throw new IllegalArgumentException("Please provide a kid");
}
if (keyPair == null) {
throw new IllegalArgumentException("Please provide a KeyPair");
}
if (keyPair.getPublic() == null || !(keyPair.getPublic() instanceof RSAPublicKey)) {
throw new IllegalArgumentException("The KeyPair is not an RsaKey");
}
_kid = kid;
_keyPair = keyPair;
_provider = provider;
}
/**
* 公钥解密
* @param data
* @param publicKey
* @return
*/
public static String publicDecrypt(String data, RSAPublicKey publicKey) {
try {
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);
} catch (Exception e) {
throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
}
}
@GetMapping("/.well-known/jwks.json")
@ResponseBody
public Map<String, Object> getKey() {
RSAPublicKey publicKey = (RSAPublicKey) this.keyPair.getPublic();
RSAKey key = new RSAKey.Builder(publicKey).build();
return new JWKSet(key).toJSONObject();
}
/**
* <p>
* 生成密钥对(公钥和私钥)
* </p>
*
* @return
* @throws Exception
*/
public static Map<String, Object> genKeyPair() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<String, Object>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
static int getRSAKeyLength(PublicKey key) {
BigInteger modulus;
if (key instanceof RSAPublicKey) {
modulus = ((RSAPublicKey)key).getModulus();
} else {
RSAPublicKeySpec spec = getRSAPublicKeySpec(key);
modulus = spec.getModulus();
}
return modulus.bitLength();
}
@Test(expectedExceptions = { ParseException.class }, description = "Illustrate validation of exp")
public void testNimbusFailExpired() throws Exception {
HashMap<String, Long> timeClaims = new HashMap<>();
HashSet<TokenUtils.InvalidClaims> invalidFields = new HashSet<>();
invalidFields.add(TokenUtils.InvalidClaims.EXP);
String token = TokenUtils.generateTokenString("/Token1.json", invalidFields, timeClaims);
RSAPublicKey publicKey = (RSAPublicKey) TokenUtils.readPublicKey("/publicKey.pem");
JWTAuthContextInfo contextInfo = new JWTAuthContextInfo(publicKey, "https://server.example.com");
contextInfo.setExpGracePeriodSecs(60);
JsonWebToken jwt = validateToken(token, contextInfo);
}
public static ClientMessageService
getServerService(
String server_address,
int server_port,
int timeout_secs,
String msg_type_id,
RSAPublicKey public_key )
throws IOException
{
return new SecureMessageServiceClientHelper( server_address, server_port, timeout_secs, msg_type_id, public_key );
}
public static void main(String[] args) throws FileNotFoundException, IOException, NoSuchAlgorithmException, NoSuchProviderException {
Security.addProvider(new BouncyCastleProvider());
LOGGER.info("BouncyCastle provider added.");
KeyPair keyPair = generateRSAKeyPair();
RSAPrivateKey priv = (RSAPrivateKey) keyPair.getPrivate();
RSAPublicKey pub = (RSAPublicKey) keyPair.getPublic();
writePemFile(priv, "RSA PRIVATE KEY", "id_rsa");
writePemFile(pub, "RSA PUBLIC KEY", "id_rsa.pub");
}
/**
* 初始化密钥
*
* @return
* @throws Exception
*/
public static Map<String, Object> initKey() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator
.getInstance(Algorithm.RSA.getType());
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 公钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 私钥
Map<String, Object> keyMap = new HashMap<String, Object>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
public static String getPublicKeySshFingerprint(PublicKey publicKey) throws NoSuchAlgorithmException, IOException {
if (publicKey instanceof RSAPublicKey) {
return getPublicKeySshFingerprint((RSAPublicKey) publicKey);
}
throw new NoSuchAlgorithmException("Unsopported PublicKey type");
}
static int getRSAKeyLength(PublicKey key) {
BigInteger modulus;
if (key instanceof RSAPublicKey) {
modulus = ((RSAPublicKey)key).getModulus();
} else {
RSAPublicKeySpec spec = getRSAPublicKeySpec(key);
modulus = spec.getModulus();
}
return modulus.bitLength();
}
public static AttestationObject createAttestationObjectWithSelfPackedRSAAttestationStatement(byte[] clientDataHash) {
KeyPair keyPair = RSAUtil.createKeyPair();
RSACOSEKey rsaCredentialPublicKey = RSACOSEKey.create((RSAPublicKey) keyPair.getPublic(), COSEAlgorithmIdentifier.RS256);
AuthenticatorData<RegistrationExtensionAuthenticatorOutput<?>> authenticatorData = createAuthenticatorData(rsaCredentialPublicKey);
byte[] authenticatorDataBytes = authenticatorDataConverter.convert(authenticatorData);
byte[] signedData = createSignedData(authenticatorDataBytes, clientDataHash);
byte[] signature = calculateSignature(keyPair.getPrivate(), signedData);
return new AttestationObject(authenticatorData, TestAttestationStatementUtil.createSelfPackedAttestationStatement(COSEAlgorithmIdentifier.RS256, signature));
}
public static RSAPublicKey parseRSAPublicKey(String pem) throws IOException, ServletException {
final String pemHeader = "-----BEGIN CERTIFICATE-----\n";
final String pemFooter = "\n-----END CERTIFICATE-----";
String fullPem = pemHeader + pem + pemFooter;
PublicKey key = null;
try {
CertificateFactory fact = CertificateFactory.getInstance("X.509");
ByteArrayInputStream is = new ByteArrayInputStream(
FileUtils.readFileToString(new File(pem)).getBytes("UTF8"));
X509Certificate cer = (X509Certificate) fact.generateCertificate(is);
key = cer.getPublicKey();
} catch (CertificateException ce) {
String message = null;
if (pem.startsWith(pemHeader)) {
message = "CertificateException - be sure not to include PEM header "
+ "and footer in the PEM configuration element.";
} else {
message = "CertificateException - PEM may be corrupt";
}
throw new ServletException(message, ce);
} catch (UnsupportedEncodingException uee) {
throw new ServletException(uee);
} catch (IOException e) {
throw new IOException(e);
}
return (RSAPublicKey) key;
}