下面列出了java.security.KeyStore#getEntry ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private boolean verifySignedJAXBObject(Object obj) {
try {
DOMResult domResult = new DOMResult();
JAXB.marshal(obj, domResult);
Document doc = ((Document) domResult.getNode());
Element docElement = doc.getDocumentElement();
KeyStore ks = KeyStore.getInstance(SIGNATURE_KEYSTORE_TYPE);
URL url = Thread.currentThread().getContextClassLoader().getResource(SIGNATURE_KEYSTORE);
ks.load(url.openStream(), SIGNATURE_KEYSTORE_PASSWORD.toCharArray());
KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(SIGNATURE_KEYSTORE_ALIAS, new KeyStore.PasswordProtection(SIGNATURE_KEYSTORE_PASSWORD.toCharArray()));
PrivateKey privateKey = keyEntry.getPrivateKey();
Certificate origCert = keyEntry.getCertificate();
PublicKey validatingKey = origCert.getPublicKey();
return TckSigningUtil.verifySignature(docElement, validatingKey);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static String encrypt(String data) {
String encryptedString = null;
try{
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
final KeyStore.SecretKeyEntry keyEntry = (KeyStore.SecretKeyEntry) keyStore.getEntry("Empire", null);
final SecretKey secretKey = keyEntry.getSecretKey();
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] iv = cipher.getIV();
byte[] encrypted = cipher.doFinal(data.getBytes("UTF-8"));
byte[] encrypted1 = new byte[iv.length + encrypted.length];
System.arraycopy(iv, 0, encrypted1, 0, iv.length);
System.arraycopy(encrypted, 0, encrypted1, iv.length, encrypted.length);
encryptedString = Base64.encodeToString(encrypted1, Base64.DEFAULT);
} catch (Exception e) {
System.out.println(e);
}
return encryptedString;
}
@Nullable
private KeyStore.Entry getKeyStoreEntry(boolean shouldGenerateKey, String alias) {
try {
KeyStore keyStore = getKeyStoreAndLoad();
KeyStore.Entry entry = keyStore.getEntry(alias, null);
if (entry == null) {
if (shouldGenerateKey) {
generateKeyRsa(alias);
entry = keyStore.getEntry(alias, null);
}
}
return entry;
} catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableEntryException e) {
throw new KeyStoreAccessException("Unable to access keystore", e);
}
}
private Certificate validateServerKeyStore() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableEntryException,
InvalidKeyException, NoSuchProviderException, SignatureException {
serverConfig = objectMapper.readValue(new ByteArrayInputStream(serverConfigFileOutputStream.toByteArray()), TlsConfig.class);
KeyStore serverKeyStore = KeyStoreUtils.getKeyStore(serverConfig.getKeyStoreType());
serverKeyStore.load(new ByteArrayInputStream(serverKeyStoreOutputStream.toByteArray()), serverConfig.getKeyStorePassword().toCharArray());
String keyPassword = serverConfig.getKeyPassword();
KeyStore.Entry serverKeyEntry = serverKeyStore.getEntry(TlsToolkitStandalone.NIFI_KEY,
new KeyStore.PasswordProtection(keyPassword == null ? serverConfig.getKeyStorePassword().toCharArray() : keyPassword.toCharArray()));
assertTrue(serverKeyEntry instanceof KeyStore.PrivateKeyEntry);
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) serverKeyEntry;
Certificate[] certificateChain = privateKeyEntry.getCertificateChain();
assertEquals(1, certificateChain.length);
Certificate caCertificate = certificateChain[0];
caCertificate.verify(caCertificate.getPublicKey());
assertPrivateAndPublicKeyMatch(privateKeyEntry.getPrivateKey(), caCertificate.getPublicKey());
return caCertificate;
}
private void validateClient(Certificate caCertificate) throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException,
UnrecoverableEntryException, InvalidKeyException, NoSuchProviderException, SignatureException {
clientConfig = objectMapper.readValue(new ByteArrayInputStream(clientConfigFileOutputStream.toByteArray()), TlsClientConfig.class);
KeyStore clientKeyStore = KeyStoreUtils.getKeyStore(clientConfig.getKeyStoreType());
clientKeyStore.load(new ByteArrayInputStream(clientKeyStoreOutputStream.toByteArray()), clientConfig.getKeyStorePassword().toCharArray());
String keyPassword = clientConfig.getKeyPassword();
KeyStore.Entry clientKeyStoreEntry = clientKeyStore.getEntry(TlsToolkitStandalone.NIFI_KEY,
new KeyStore.PasswordProtection(keyPassword == null ? clientConfig.getKeyStorePassword().toCharArray() : keyPassword.toCharArray()));
assertTrue(clientKeyStoreEntry instanceof KeyStore.PrivateKeyEntry);
KeyStore.PrivateKeyEntry clientPrivateKeyEntry = (KeyStore.PrivateKeyEntry) clientKeyStoreEntry;
Certificate[] certificateChain = clientPrivateKeyEntry.getCertificateChain();
assertEquals(2, certificateChain.length);
assertEquals(caCertificate, certificateChain[1]);
certificateChain[0].verify(caCertificate.getPublicKey());
assertPrivateAndPublicKeyMatch(clientPrivateKeyEntry.getPrivateKey(), certificateChain[0].getPublicKey());
KeyStore clientTrustStore = KeyStoreUtils.getTrustStore(KeystoreType.JKS.toString());
clientTrustStore.load(new ByteArrayInputStream(clientTrustStoreOutputStream.toByteArray()), clientConfig.getTrustStorePassword().toCharArray());
assertEquals(caCertificate, clientTrustStore.getCertificate(TlsToolkitStandalone.NIFI_CERT));
}
private static void check(String encodedBlob) throws Exception {
byte[] blob = new byte[encodedBlob.length() * 2];
for (int i = 0; i < blob.length; ) {
final char ch = encodedBlob.charAt(i / 2);
blob[i++] = (byte) (ch >> 8);
blob[i++] = (byte) ch;
}
KeyStore store = KeyStore.getInstance("PKCS12");
store.load(new ByteArrayInputStream(blob), new char[0]);
if (!store.aliases().nextElement().equals("test"))
throw new Exception("test alias not found");
KeyStore.PrivateKeyEntry e =
(KeyStore.PrivateKeyEntry) store.getEntry("test",
new KeyStore.PasswordProtection(new char[0]));
X509Certificate cert = (X509Certificate) e.getCertificateChain()[0];
if (!cert.getSubjectDN().toString().equals("CN=Test Key"))
throw new Exception("invalid certificate subject DN");
RSAPrivateCrtKey key = (RSAPrivateCrtKey) e.getPrivateKey();
if (!key.getPublicExponent().equals(BigInteger.valueOf(65537)))
throw new Exception("invalid public exponent");
}
private static void check(String encodedBlob) throws Exception {
byte[] blob = new byte[encodedBlob.length() * 2];
for (int i = 0; i < blob.length; ) {
final char ch = encodedBlob.charAt(i / 2);
blob[i++] = (byte) (ch >> 8);
blob[i++] = (byte) ch;
}
KeyStore store = KeyStore.getInstance("PKCS12");
store.load(new ByteArrayInputStream(blob), new char[0]);
if (!store.aliases().nextElement().equals("test"))
throw new Exception("test alias not found");
KeyStore.PrivateKeyEntry e =
(KeyStore.PrivateKeyEntry) store.getEntry("test",
new KeyStore.PasswordProtection(new char[0]));
X509Certificate cert = (X509Certificate) e.getCertificateChain()[0];
if (!cert.getSubjectDN().toString().equals("CN=Test Key"))
throw new Exception("invalid certificate subject DN");
RSAPrivateCrtKey key = (RSAPrivateCrtKey) e.getPrivateKey();
if (!key.getPublicExponent().equals(BigInteger.valueOf(65537)))
throw new Exception("invalid public exponent");
}
private Certificate validateServerKeyStore() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableEntryException,
InvalidKeyException, NoSuchProviderException, SignatureException {
serverConfig = objectMapper.readValue(new ByteArrayInputStream(serverConfigFileOutputStream.toByteArray()), TlsConfig.class);
KeyStore serverKeyStore = KeyStoreUtils.getKeyStore(serverConfig.getKeyStoreType());
serverKeyStore.load(new ByteArrayInputStream(serverKeyStoreOutputStream.toByteArray()), serverConfig.getKeyStorePassword().toCharArray());
String keyPassword = serverConfig.getKeyPassword();
KeyStore.Entry serverKeyEntry = serverKeyStore.getEntry(TlsToolkitStandalone.NIFI_KEY,
new KeyStore.PasswordProtection(keyPassword == null ? serverConfig.getKeyStorePassword().toCharArray() : keyPassword.toCharArray()));
assertTrue(serverKeyEntry instanceof KeyStore.PrivateKeyEntry);
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) serverKeyEntry;
Certificate[] certificateChain = privateKeyEntry.getCertificateChain();
assertEquals(1, certificateChain.length);
Certificate caCertificate = certificateChain[0];
caCertificate.verify(caCertificate.getPublicKey());
assertPrivateAndPublicKeyMatch(privateKeyEntry.getPrivateKey(), caCertificate.getPublicKey());
return caCertificate;
}
/**
* Encrypts randomly generated AES key using RSA public key
* @param secretKey
* @return
*/
private byte[] encryptAESKey(byte[] secretKey) throws KeyStoreException,
UnrecoverableEntryException, NoSuchAlgorithmException, IOException,
CertificateException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_ANDROID);
keyStore.load(null);
KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry)
keyStore.getEntry(KEY_ALIAS_AMAZE, null);
Cipher cipher = Cipher.getInstance(ALGO_RSA, "AndroidOpenSSL");
cipher.init(Cipher.ENCRYPT_MODE, keyEntry.getCertificate().getPublicKey());
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
CipherOutputStream outputStream = new CipherOutputStream(byteArrayOutputStream, cipher);
outputStream.write(secretKey);
outputStream.close();
return byteArrayOutputStream.toByteArray();
}
private void checkAttrs() throws UnrecoverableEntryException,
GeneralSecurityException, NoSuchAlgorithmException,
KeyStoreException, IOException {
KeyStore ks = Utils.loadKeyStore(WORKING_DIRECTORY
+ File.separator
+ KESTORE_NEW, Utils.KeyStoreType.pkcs12, PASSWORD);
KeyStore.Entry keyStoreEntry = ks.getEntry(ALIAS,
new KeyStore.PasswordProtection(KEY_PASSWORD));
out.println("Attributes after store:");
//print attribute values
keyStoreEntry.getAttributes().stream().forEach((attr) -> {
out.println(attr.getName() + ", '" + attr.getValue() + "'");
});
Arrays.stream(ATTR_SET).forEach((attr) -> {
if (!keyStoreEntry.getAttributes().contains(attr)) {
throw new RuntimeException("Entry doesn't contain attribute: ("
+ attr.getName() + ", '" + attr.getValue() + "')");
}
});
}
@Test
public void createKeyStore() throws Exception {
KeyStore keyStore = KeyStoreUtil.createDockerKeyStore(getFile("certpath"));
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry("docker",
new KeyStore.PasswordProtection("docker".toCharArray()));
assertNotNull(pkEntry);
assertNotNull(pkEntry.getCertificate());
assertNotNull(keyStore.getCertificate("cn=ca-test,o=internet widgits pty ltd,st=some-state,c=cr"));
assertNotNull(keyStore.getCertificate("cn=ca-test-2,o=internet widgits pty ltd,st=some-state,c=cr"));
}
String decryptString(String alias) {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding");
output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());
SharedPreferences sharedPref =PreferenceManager.getDefaultSharedPreferences(c);
String cipherText = sharedPref.getString("cypher",null);
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), output);
ArrayList<Byte> values = new ArrayList<>();
int nextByte;
while ((nextByte = cipherInputStream.read()) != -1) {
values.add((byte)nextByte);
}
byte[] bytes = new byte[values.size()];
for(int i = 0; i < bytes.length; i++) {
bytes[i] = values.get(i).byteValue();
}
String finalText = new String(bytes, 0, bytes.length, "UTF-8");
return finalText;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Test
public void createKeyStore() throws Exception {
KeyStore keyStore = KeyStoreUtil.createDockerKeyStore(getFile("certpath"));
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry("docker",
new KeyStore.PasswordProtection("docker".toCharArray()));
assertNotNull(pkEntry);
assertNotNull(pkEntry.getCertificate());
assertNotNull(keyStore.getCertificate("cn=ca-test,o=internet widgits pty ltd,st=some-state,c=cr"));
assertNotNull(keyStore.getCertificate("cn=ca-test-2,o=internet widgits pty ltd,st=some-state,c=cr"));
}
private void run(String keystoreType) throws Exception {
char[] pw = "password".toCharArray();
KeyStore ks = KeyStore.getInstance(keystoreType);
ks.load(null, pw);
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128);
SecretKey key = kg.generateKey();
KeyStore.SecretKeyEntry ske = new KeyStore.SecretKeyEntry(key);
KeyStore.ProtectionParameter kspp = new KeyStore.PasswordProtection(pw);
ks.setEntry(ALIAS, ske, kspp);
File ksFile = File.createTempFile("test", ".test");
try (FileOutputStream fos = new FileOutputStream(ksFile)) {
ks.store(fos, pw);
fos.flush();
}
// now see if we can get it back
try (FileInputStream fis = new FileInputStream(ksFile)) {
KeyStore ks2 = KeyStore.getInstance(keystoreType);
ks2.load(fis, pw);
KeyStore.Entry entry = ks2.getEntry(ALIAS, kspp);
SecretKey keyIn = ((KeyStore.SecretKeyEntry)entry).getSecretKey();
if (Arrays.equals(key.getEncoded(), keyIn.getEncoded())) {
System.err.println("OK: worked just fine with " + keystoreType +
" keystore");
} else {
System.err.println("ERROR: keys are NOT equal after storing in "
+ keystoreType + " keystore");
}
}
}
private void run(String keystoreType) throws Exception {
char[] pw = "password".toCharArray();
KeyStore ks = KeyStore.getInstance(keystoreType);
ks.load(null, pw);
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128);
SecretKey key = kg.generateKey();
KeyStore.SecretKeyEntry ske = new KeyStore.SecretKeyEntry(key);
KeyStore.ProtectionParameter kspp = new KeyStore.PasswordProtection(pw);
ks.setEntry(ALIAS, ske, kspp);
File ksFile = File.createTempFile("test", ".test");
try (FileOutputStream fos = new FileOutputStream(ksFile)) {
ks.store(fos, pw);
fos.flush();
}
// now see if we can get it back
try (FileInputStream fis = new FileInputStream(ksFile)) {
KeyStore ks2 = KeyStore.getInstance(keystoreType);
ks2.load(fis, pw);
KeyStore.Entry entry = ks2.getEntry(ALIAS, kspp);
SecretKey keyIn = ((KeyStore.SecretKeyEntry)entry).getSecretKey();
if (Arrays.equals(key.getEncoded(), keyIn.getEncoded())) {
System.err.println("OK: worked just fine with " + keystoreType +
" keystore");
} else {
System.err.println("ERROR: keys are NOT equal after storing in "
+ keystoreType + " keystore");
}
}
}
private void testKeyStoreRoundTrip(KeyStoreSupplier initialKeyStoreSupplier, KeyStoreSupplier reloadKeyStoreSupplier, char[] keyPassword) throws GeneralSecurityException, IOException {
KeyStore keyStore = initialKeyStoreSupplier.get();
keyStore.load(null, null);
keyStore.setKeyEntry(ALIAS, issuedCertificateKeyPair.getPrivate(), keyPassword, new Certificate[]{issuedCertificate, caCertificate});
KeyStore roundTrip = roundTrip(keyStore, reloadKeyStoreSupplier);
KeyStore.Entry entry = roundTrip.getEntry(ALIAS, new KeyStore.PasswordProtection(keyPassword));
assertTrue(entry instanceof KeyStore.PrivateKeyEntry);
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) entry;
Certificate[] certificateChain = privateKeyEntry.getCertificateChain();
assertArrayEquals(new Certificate[]{issuedCertificate, caCertificate}, certificateChain);
assertEquals(issuedCertificateKeyPair.getPrivate(), privateKeyEntry.getPrivateKey());
assertEquals(issuedCertificateKeyPair.getPublic(), certificateChain[0].getPublicKey());
}
private static byte[] rsaEncrypt(byte[] secret) throws Exception {
KeyStore keyStore = KeyStore.getInstance(AndroidKeyStore);
keyStore.load(null);
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(KEY_ALIAS, null);
// Encrypt the text
Cipher inputCipher = Cipher.getInstance(RSA_MODE);
inputCipher.init(Cipher.ENCRYPT_MODE, privateKeyEntry.getCertificate().getPublicKey());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, inputCipher);
cipherOutputStream.write(secret);
cipherOutputStream.close();
return outputStream.toByteArray();
}
/**
* Given some data and a signature, uses the key pair stored in the Android
* Key Store to verify that the data was signed by this application, using
* that key pair.
*
* @param input
* The data to be verified.
* @param signatureStr
* The signature provided for the data.
* @return A boolean value telling you whether the signature is valid or
* not.
*/
public boolean verifyData(String input, String signatureStr)
throws KeyStoreException, CertificateException,
NoSuchAlgorithmException, IOException, UnrecoverableEntryException,
InvalidKeyException, SignatureException {
byte[] data = input.getBytes();
byte[] signature;
// Make sure the signature string exists. If not, bail out, nothing to
// do.
if (signatureStr == null) {
Log.w(TAG, "Invalid signature.");
Log.w(TAG, "Exiting verifyData()...");
return false;
}
try {
// The signature is going to be examined as a byte array,
// not as a base64 encoded string.
signature = Base64.decode(signatureStr, Base64.DEFAULT);
} catch (IllegalArgumentException e) {
// signatureStr wasn't null, but might not have been encoded
// properly.
// It's not a valid Base64 string.
return false;
}
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
// Weird artifact of Java API. If you don't have an InputStream to load,
// you still need
// to call "load", or it'll crash.
ks.load(null);
// Load the key pair from the Android Key Store
KeyStore.Entry entry = ks.getEntry(mAlias, null);
if (entry == null) {
Log.w(TAG, "No key found under alias: " + mAlias);
Log.w(TAG, "Exiting verifyData()...");
return false;
}
if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
Log.w(TAG, "Not an instance of a PrivateKeyEntry");
return false;
}
// This class doesn't actually represent the signature,
// just the engine for creating/verifying signatures, using
// the specified algorithm.
Signature s = Signature
.getInstance(SecurityConstants.SIGNATURE_SHA256withRSA);
// Verify the data.
s.initVerify(((KeyStore.PrivateKeyEntry) entry).getCertificate());
s.update(data);
boolean valid = s.verify(signature);
return valid;
}
/**
* Recovers entry associated with given alias.
*
* @return an array of objects, where the 1st element in the array is the
* recovered entry, and the 2nd element is the password used to
* recover it (null if no password).
*/
private Pair<Entry,char[]> recoverEntry(KeyStore ks,
String alias,
char[] pstore,
char[] pkey) throws Exception {
if (ks.containsAlias(alias) == false) {
MessageFormat form = new MessageFormat
(rb.getString("Alias.alias.does.not.exist"));
Object[] source = {alias};
throw new Exception(form.format(source));
}
PasswordProtection pp = null;
Entry entry;
try {
// First attempt to access entry without key password
// (PKCS11 entry or trusted certificate entry, for example)
entry = ks.getEntry(alias, pp);
pkey = null;
} catch (UnrecoverableEntryException une) {
if(P11KEYSTORE.equalsIgnoreCase(ks.getType()) ||
KeyStoreUtil.isWindowsKeyStore(ks.getType())) {
// should not happen, but a possibility
throw une;
}
// entry is protected
if (pkey != null) {
// try provided key password
pp = new PasswordProtection(pkey);
entry = ks.getEntry(alias, pp);
} else {
// try store pass
try {
pp = new PasswordProtection(pstore);
entry = ks.getEntry(alias, pp);
pkey = pstore;
} catch (UnrecoverableEntryException une2) {
if (P12KEYSTORE.equalsIgnoreCase(ks.getType())) {
// P12 keystore currently does not support separate
// store and entry passwords
throw une2;
} else {
// prompt for entry password
pkey = getKeyPasswd(alias, null, null);
pp = new PasswordProtection(pkey);
entry = ks.getEntry(alias, pp);
}
}
}
}
return Pair.of(entry, pkey);
}
/**
* Recovers entry associated with given alias.
*
* @return an array of objects, where the 1st element in the array is the
* recovered entry, and the 2nd element is the password used to
* recover it (null if no password).
*/
private Pair<Entry,char[]> recoverEntry(KeyStore ks,
String alias,
char[] pstore,
char[] pkey) throws Exception {
if (ks.containsAlias(alias) == false) {
MessageFormat form = new MessageFormat
(rb.getString("Alias.alias.does.not.exist"));
Object[] source = {alias};
throw new Exception(form.format(source));
}
PasswordProtection pp = null;
Entry entry;
try {
// First attempt to access entry without key password
// (PKCS11 entry or trusted certificate entry, for example)
entry = ks.getEntry(alias, pp);
pkey = null;
} catch (UnrecoverableEntryException une) {
if(P11KEYSTORE.equalsIgnoreCase(ks.getType()) ||
KeyStoreUtil.isWindowsKeyStore(ks.getType())) {
// should not happen, but a possibility
throw une;
}
// entry is protected
if (pkey != null) {
// try provided key password
pp = new PasswordProtection(pkey);
entry = ks.getEntry(alias, pp);
} else {
// try store pass
try {
pp = new PasswordProtection(pstore);
entry = ks.getEntry(alias, pp);
pkey = pstore;
} catch (UnrecoverableEntryException une2) {
if (P12KEYSTORE.equalsIgnoreCase(ks.getType())) {
// P12 keystore currently does not support separate
// store and entry passwords
throw une2;
} else {
// prompt for entry password
pkey = getKeyPasswd(alias, null, null);
pp = new PasswordProtection(pkey);
entry = ks.getEntry(alias, pp);
}
}
}
}
return Pair.of(entry, pkey);
}