6732372: Some MSCAPI native methods not returning correct exceptions
Reviewed-by: mullan
This commit is contained in:
parent
9d72155fc5
commit
d617d849a0
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -121,15 +121,16 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
|
|||||||
}
|
}
|
||||||
random.nextBytes(seed);
|
random.nextBytes(seed);
|
||||||
|
|
||||||
long[] handles = generateECKeyPair(keySize, encodedParams, seed);
|
|
||||||
|
|
||||||
// The 'params' object supplied above is equivalent to the native one
|
|
||||||
// so there is no need to fetch it.
|
|
||||||
|
|
||||||
// handles[0] points to the native private key
|
|
||||||
BigInteger s = new BigInteger(1, getEncodedBytes(handles[0]));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
long[] handles = generateECKeyPair(keySize, encodedParams, seed);
|
||||||
|
|
||||||
|
// The 'params' object supplied above is equivalent to the native
|
||||||
|
// one so there is no need to fetch it.
|
||||||
|
|
||||||
|
// handles[0] points to the native private key
|
||||||
|
BigInteger s = new BigInteger(1, getEncodedBytes(handles[0]));
|
||||||
|
|
||||||
PrivateKey privateKey =
|
PrivateKey privateKey =
|
||||||
new ECPrivateKeyImpl(s, (ECParameterSpec)params);
|
new ECPrivateKeyImpl(s, (ECParameterSpec)params);
|
||||||
|
|
||||||
@ -163,7 +164,7 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
|
|||||||
* The first handle points to the private key, the second to the public key.
|
* The first handle points to the private key, the second to the public key.
|
||||||
*/
|
*/
|
||||||
private static native long[] generateECKeyPair(int keySize,
|
private static native long[] generateECKeyPair(int keySize,
|
||||||
byte[] encodedParams, byte[] seed);
|
byte[] encodedParams, byte[] seed) throws GeneralSecurityException;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extracts the encoded key data using the supplied handle.
|
* Extracts the encoded key data using the supplied handle.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -31,6 +31,7 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
import java.security.KeyStoreSpi;
|
import java.security.KeyStoreSpi;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.UnrecoverableKeyException;
|
import java.security.UnrecoverableKeyException;
|
||||||
@ -123,6 +124,7 @@ abstract class KeyStore extends KeyStoreSpi {
|
|||||||
* Sets the private key for the keystore entry.
|
* Sets the private key for the keystore entry.
|
||||||
*/
|
*/
|
||||||
void setPrivateKey(RSAPrivateCrtKey key)
|
void setPrivateKey(RSAPrivateCrtKey key)
|
||||||
|
throws InvalidKeyException, KeyStoreException
|
||||||
{
|
{
|
||||||
byte[] modulusBytes = key.getModulus().toByteArray();
|
byte[] modulusBytes = key.getModulus().toByteArray();
|
||||||
|
|
||||||
@ -158,7 +160,7 @@ abstract class KeyStore extends KeyStoreSpi {
|
|||||||
* Sets the certificate chain for the keystore entry.
|
* Sets the certificate chain for the keystore entry.
|
||||||
*/
|
*/
|
||||||
void setCertificateChain(X509Certificate[] chain)
|
void setCertificateChain(X509Certificate[] chain)
|
||||||
throws CertificateException
|
throws CertificateException, KeyStoreException
|
||||||
{
|
{
|
||||||
for (int i = 0; i < chain.length; i++) {
|
for (int i = 0; i < chain.length; i++) {
|
||||||
byte[] encoding = chain[i].getEncoded();
|
byte[] encoding = chain[i].getEncoded();
|
||||||
@ -404,13 +406,16 @@ abstract class KeyStore extends KeyStoreSpi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
entry.setAlias(alias);
|
entry.setAlias(alias);
|
||||||
entry.setPrivateKey((RSAPrivateCrtKey) key);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
entry.setPrivateKey((RSAPrivateCrtKey) key);
|
||||||
entry.setCertificateChain((X509Certificate[]) chain);
|
entry.setCertificateChain((X509Certificate[]) chain);
|
||||||
|
|
||||||
} catch (CertificateException ce) {
|
} catch (CertificateException ce) {
|
||||||
throw new KeyStoreException(ce);
|
throw new KeyStoreException(ce);
|
||||||
|
|
||||||
|
} catch (InvalidKeyException ike) {
|
||||||
|
throw new KeyStoreException(ike);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -537,7 +542,7 @@ abstract class KeyStore extends KeyStoreSpi {
|
|||||||
removeCertificate(getName(), alias, encoding,
|
removeCertificate(getName(), alias, encoding,
|
||||||
encoding.length);
|
encoding.length);
|
||||||
|
|
||||||
} catch (CertificateEncodingException e) {
|
} catch (CertificateException e) {
|
||||||
throw new KeyStoreException("Cannot remove entry: " +
|
throw new KeyStoreException("Cannot remove entry: " +
|
||||||
e);
|
e);
|
||||||
}
|
}
|
||||||
@ -754,8 +759,14 @@ abstract class KeyStore extends KeyStoreSpi {
|
|||||||
// Clear all key entries
|
// Clear all key entries
|
||||||
entries.clear();
|
entries.clear();
|
||||||
|
|
||||||
// Load keys and/or certificate chains
|
try {
|
||||||
loadKeysOrCertificateChains(getName(), entries);
|
|
||||||
|
// Load keys and/or certificate chains
|
||||||
|
loadKeysOrCertificateChains(getName(), entries);
|
||||||
|
|
||||||
|
} catch (KeyStoreException e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -868,7 +879,7 @@ abstract class KeyStore extends KeyStoreSpi {
|
|||||||
* @param entries Collection of key/certificate.
|
* @param entries Collection of key/certificate.
|
||||||
*/
|
*/
|
||||||
private native void loadKeysOrCertificateChains(String name,
|
private native void loadKeysOrCertificateChains(String name,
|
||||||
Collection<KeyEntry> entries);
|
Collection<KeyEntry> entries) throws KeyStoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores a DER-encoded certificate into the certificate store
|
* Stores a DER-encoded certificate into the certificate store
|
||||||
@ -879,7 +890,7 @@ abstract class KeyStore extends KeyStoreSpi {
|
|||||||
*/
|
*/
|
||||||
private native void storeCertificate(String name, String alias,
|
private native void storeCertificate(String name, String alias,
|
||||||
byte[] encoding, int encodingLength, long hCryptProvider,
|
byte[] encoding, int encodingLength, long hCryptProvider,
|
||||||
long hCryptKey);
|
long hCryptKey) throws CertificateException, KeyStoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the certificate from the certificate store
|
* Removes the certificate from the certificate store
|
||||||
@ -889,14 +900,16 @@ abstract class KeyStore extends KeyStoreSpi {
|
|||||||
* @param encoding DER-encoded certificate.
|
* @param encoding DER-encoded certificate.
|
||||||
*/
|
*/
|
||||||
private native void removeCertificate(String name, String alias,
|
private native void removeCertificate(String name, String alias,
|
||||||
byte[] encoding, int encodingLength);
|
byte[] encoding, int encodingLength)
|
||||||
|
throws CertificateException, KeyStoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys the key container.
|
* Destroys the key container.
|
||||||
*
|
*
|
||||||
* @param keyContainerName The name of the key container.
|
* @param keyContainerName The name of the key container.
|
||||||
*/
|
*/
|
||||||
private native void destroyKeyContainer(String keyContainerName);
|
private native void destroyKeyContainer(String keyContainerName)
|
||||||
|
throws KeyStoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a private-key BLOB from a key's components.
|
* Generates a private-key BLOB from a key's components.
|
||||||
@ -910,8 +923,8 @@ abstract class KeyStore extends KeyStoreSpi {
|
|||||||
byte[] primeQ,
|
byte[] primeQ,
|
||||||
byte[] exponentP,
|
byte[] exponentP,
|
||||||
byte[] exponentQ,
|
byte[] exponentQ,
|
||||||
byte[] crtCoefficient);
|
byte[] crtCoefficient) throws InvalidKeyException;
|
||||||
|
|
||||||
private native RSAPrivateKey storePrivateKey(byte[] keyBlob,
|
private native RSAPrivateKey storePrivateKey(byte[] keyBlob,
|
||||||
String keyContainerName, int keySize);
|
String keyContainerName, int keySize) throws KeyStoreException;
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,12 @@ public final class RSACipher extends CipherSpi {
|
|||||||
byte[] keyBlob = RSASignature.generatePublicKeyBlob(
|
byte[] keyBlob = RSASignature.generatePublicKeyBlob(
|
||||||
keyBitLength, modulusBytes, exponentBytes);
|
keyBitLength, modulusBytes, exponentBytes);
|
||||||
|
|
||||||
key = RSASignature.importPublicKey(keyBlob, keyBitLength);
|
try {
|
||||||
|
key = RSASignature.importPublicKey(keyBlob, keyBitLength);
|
||||||
|
|
||||||
|
} catch (KeyStoreException e) {
|
||||||
|
throw new InvalidKeyException(e);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidKeyException("Unsupported key type: " + key);
|
throw new InvalidKeyException("Unsupported key type: " + key);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -105,14 +105,20 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
|
|||||||
// generate the keypair. See JCA doc
|
// generate the keypair. See JCA doc
|
||||||
public KeyPair generateKeyPair() {
|
public KeyPair generateKeyPair() {
|
||||||
|
|
||||||
// Generate each keypair in a unique key container
|
try {
|
||||||
RSAKeyPair keys =
|
|
||||||
generateRSAKeyPair(keySize,
|
|
||||||
"{" + UUID.randomUUID().toString() + "}");
|
|
||||||
|
|
||||||
return new KeyPair(keys.getPublic(), keys.getPrivate());
|
// Generate each keypair in a unique key container
|
||||||
|
RSAKeyPair keys =
|
||||||
|
generateRSAKeyPair(keySize,
|
||||||
|
"{" + UUID.randomUUID().toString() + "}");
|
||||||
|
|
||||||
|
return new KeyPair(keys.getPublic(), keys.getPrivate());
|
||||||
|
|
||||||
|
} catch (KeyException e) {
|
||||||
|
throw new ProviderException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native RSAKeyPair generateRSAKeyPair(int keySize,
|
private static native RSAKeyPair generateRSAKeyPair(int keySize,
|
||||||
String keyContainerName);
|
String keyContainerName) throws KeyException;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,9 @@ package sun.security.mscapi;
|
|||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.KeyException;
|
||||||
import java.security.KeyRep;
|
import java.security.KeyRep;
|
||||||
|
import java.security.ProviderException;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
|
|
||||||
import sun.security.rsa.RSAPublicKeyImpl;
|
import sun.security.rsa.RSAPublicKeyImpl;
|
||||||
@ -89,9 +91,14 @@ class RSAPublicKey extends Key implements java.security.interfaces.RSAPublicKey
|
|||||||
public BigInteger getPublicExponent() {
|
public BigInteger getPublicExponent() {
|
||||||
|
|
||||||
if (exponent == null) {
|
if (exponent == null) {
|
||||||
publicKeyBlob = getPublicKeyBlob(hCryptKey);
|
|
||||||
|
|
||||||
exponent = new BigInteger(1, getExponent(publicKeyBlob));
|
try {
|
||||||
|
publicKeyBlob = getPublicKeyBlob(hCryptKey);
|
||||||
|
exponent = new BigInteger(1, getExponent(publicKeyBlob));
|
||||||
|
|
||||||
|
} catch (KeyException e) {
|
||||||
|
throw new ProviderException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return exponent;
|
return exponent;
|
||||||
@ -103,8 +110,14 @@ class RSAPublicKey extends Key implements java.security.interfaces.RSAPublicKey
|
|||||||
public BigInteger getModulus() {
|
public BigInteger getModulus() {
|
||||||
|
|
||||||
if (modulus == null) {
|
if (modulus == null) {
|
||||||
publicKeyBlob = getPublicKeyBlob(hCryptKey);
|
|
||||||
modulus = new BigInteger(1, getModulus(publicKeyBlob));
|
try {
|
||||||
|
publicKeyBlob = getPublicKeyBlob(hCryptKey);
|
||||||
|
modulus = new BigInteger(1, getModulus(publicKeyBlob));
|
||||||
|
|
||||||
|
} catch (KeyException e) {
|
||||||
|
throw new ProviderException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return modulus;
|
return modulus;
|
||||||
@ -147,7 +160,7 @@ class RSAPublicKey extends Key implements java.security.interfaces.RSAPublicKey
|
|||||||
encoding = new RSAPublicKeyImpl(getModulus(),
|
encoding = new RSAPublicKeyImpl(getModulus(),
|
||||||
getPublicExponent()).getEncoded();
|
getPublicExponent()).getEncoded();
|
||||||
|
|
||||||
} catch (InvalidKeyException e) {
|
} catch (KeyException e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,15 +177,15 @@ class RSAPublicKey extends Key implements java.security.interfaces.RSAPublicKey
|
|||||||
/*
|
/*
|
||||||
* Returns the Microsoft CryptoAPI representation of the key.
|
* Returns the Microsoft CryptoAPI representation of the key.
|
||||||
*/
|
*/
|
||||||
private native byte[] getPublicKeyBlob(long hCryptKey);
|
private native byte[] getPublicKeyBlob(long hCryptKey) throws KeyException;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the key's public exponent (in big-endian 2's complement format).
|
* Returns the key's public exponent (in big-endian 2's complement format).
|
||||||
*/
|
*/
|
||||||
private native byte[] getExponent(byte[] keyBlob);
|
private native byte[] getExponent(byte[] keyBlob) throws KeyException;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the key's modulus (in big-endian 2's complement format).
|
* Returns the key's modulus (in big-endian 2's complement format).
|
||||||
*/
|
*/
|
||||||
private native byte[] getModulus(byte[] keyBlob);
|
private native byte[] getModulus(byte[] keyBlob) throws KeyException;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -31,6 +31,7 @@ import java.security.PrivateKey;
|
|||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.InvalidParameterException;
|
import java.security.InvalidParameterException;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.ProviderException;
|
import java.security.ProviderException;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
@ -146,7 +147,12 @@ abstract class RSASignature extends java.security.SignatureSpi
|
|||||||
byte[] keyBlob = generatePublicKeyBlob(
|
byte[] keyBlob = generatePublicKeyBlob(
|
||||||
keyBitLength, modulusBytes, exponentBytes);
|
keyBitLength, modulusBytes, exponentBytes);
|
||||||
|
|
||||||
publicKey = importPublicKey(keyBlob, keyBitLength);
|
try {
|
||||||
|
publicKey = importPublicKey(keyBlob, keyBitLength);
|
||||||
|
|
||||||
|
} catch (KeyStoreException e) {
|
||||||
|
throw new InvalidKeyException(e);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
publicKey = (sun.security.mscapi.RSAPublicKey) key;
|
publicKey = (sun.security.mscapi.RSAPublicKey) key;
|
||||||
@ -381,11 +387,13 @@ abstract class RSASignature extends java.security.SignatureSpi
|
|||||||
*/
|
*/
|
||||||
// used by RSACipher
|
// used by RSACipher
|
||||||
static native byte[] generatePublicKeyBlob(
|
static native byte[] generatePublicKeyBlob(
|
||||||
int keyBitLength, byte[] modulus, byte[] publicExponent);
|
int keyBitLength, byte[] modulus, byte[] publicExponent)
|
||||||
|
throws InvalidKeyException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Imports a public-key BLOB.
|
* Imports a public-key BLOB.
|
||||||
*/
|
*/
|
||||||
// used by RSACipher
|
// used by RSACipher
|
||||||
static native RSAPublicKey importPublicKey(byte[] keyBlob, int keySize);
|
static native RSAPublicKey importPublicKey(byte[] keyBlob, int keySize)
|
||||||
|
throws KeyStoreException;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -40,6 +40,8 @@
|
|||||||
|
|
||||||
#define CERTIFICATE_PARSING_EXCEPTION \
|
#define CERTIFICATE_PARSING_EXCEPTION \
|
||||||
"java/security/cert/CertificateParsingException"
|
"java/security/cert/CertificateParsingException"
|
||||||
|
#define INVALID_KEY_EXCEPTION \
|
||||||
|
"java/security/InvalidKeyException"
|
||||||
#define KEY_EXCEPTION "java/security/KeyException"
|
#define KEY_EXCEPTION "java/security/KeyException"
|
||||||
#define KEYSTORE_EXCEPTION "java/security/KeyStoreException"
|
#define KEYSTORE_EXCEPTION "java/security/KeyStoreException"
|
||||||
#define PROVIDER_EXCEPTION "java/security/ProviderException"
|
#define PROVIDER_EXCEPTION "java/security/ProviderException"
|
||||||
@ -1398,7 +1400,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getPublicKeyB
|
|||||||
|
|
||||||
jbyteArray blob = NULL;
|
jbyteArray blob = NULL;
|
||||||
DWORD dwBlobLen;
|
DWORD dwBlobLen;
|
||||||
BYTE* pbKeyBlob;
|
BYTE* pbKeyBlob = NULL;
|
||||||
|
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
@ -1656,7 +1658,7 @@ jbyteArray generateKeyBlob(
|
|||||||
// Sanity check
|
// Sanity check
|
||||||
jsize jPublicExponentLength = env->GetArrayLength(jPublicExponent);
|
jsize jPublicExponentLength = env->GetArrayLength(jPublicExponent);
|
||||||
if (jPublicExponentLength > sizeof(pRsaPubKey->pubexp)) {
|
if (jPublicExponentLength > sizeof(pRsaPubKey->pubexp)) {
|
||||||
ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE);
|
ThrowException(env, INVALID_KEY_EXCEPTION, NTE_BAD_TYPE);
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
// The length argument must be the smaller of jPublicExponentLength
|
// The length argument must be the smaller of jPublicExponentLength
|
||||||
|
Loading…
Reference in New Issue
Block a user