Поиск шифрования PKCS#8 Кодированный PEM -файл программноJAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Поиск шифрования PKCS#8 Кодированный PEM -файл программно

Сообщение Anonymous »

У меня проблемы с выяснением, как правильно прочитать закрытый ключ файла PEM. Я прошел разные темы на Stackoverflow, но я не смог найти решение для него. Чего я хочу достичь, так это читать зашифрованный закрытый ключ в файле кодирования PKCS#8 из чашки и загрузить его в качестве ключа в магазине ключей в памяти. Ниже приведен пример закрытого ключа, который я пытаюсь проанализировать, пароль является секретным . Он создан чисто для обмена здесь, поэтому он не является закрытым ключом, который используется на производственной машине.
Я создал его из файла P12 со следующей командой: openssl pkcs12 -in key-pair.p12 -out key-pair.pem
valling> value (thresha-away)
Porry Pair-pair)

и < /p>
-----BEGIN RSA PRIVATE KEY-----
*
-----END RSA PRIVATE KEY-----
< /code>
Я уже использую следующий фрагмент для достижения этого: < /p>
import com.hierynomus.asn1.ASN1InputStream;
import com.hierynomus.asn1.encodingrules.der.DERDecoder;
import com.hierynomus.asn1.types.ASN1Object;
import com.hierynomus.asn1.types.constructed.ASN1Sequence;
import com.hierynomus.asn1.types.primitive.ASN1Integer;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class App {

private static final String KEYSTORE_TYPE = "PKCS12";
private static final String KEY_FACTORY_ALGORITHM = "RSA";
private static final String CERTIFICATE_TYPE = "X.509";

private static final Pattern CERTIFICATE_PATTERN = Pattern.compile("-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----", Pattern.DOTALL);
private static final Pattern PRIVATE_KEY_PATTERN = Pattern.compile("-----BEGIN PRIVATE KEY-----(.*?)-----END PRIVATE KEY-----", Pattern.DOTALL);
private static final Pattern ENCRYPTED_PRIVATE_KEY_PATTERN = Pattern.compile("-----BEGIN ENCRYPTED PRIVATE KEY-----(.*?)-----END ENCRYPTED PRIVATE KEY-----", Pattern.DOTALL);
private static final Pattern RSA_PRIVATE_KEY_PATTERN = Pattern.compile("-----BEGIN RSA PRIVATE KEY-----(.*?)-----END RSA PRIVATE KEY-----", Pattern.DOTALL);

private static final String NEW_LINE = "\n";
private static final String EMPTY = "";

public static void main(String[] args) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, InvalidKeySpecException {
String privateKeyContent = "";
String certificateContent = "";

PrivateKey privateKey = parsePrivateKey(privateKeyContent);
Certificate[] certificates = parseCertificate(certificateContent).values()
.toArray(new Certificate[]{});

KeyStore keyStore = createEmptyKeyStore();
keyStore.setKeyEntry("client", privateKey, null, certificates);
}

private static KeyStore createEmptyKeyStore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
keyStore.load(null, null);
return keyStore;
}

private static PrivateKey parsePrivateKey(String identityContent) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
KeySpec keySpec = null;

Matcher privateKeyMatcher = PRIVATE_KEY_PATTERN.matcher(identityContent);
if (privateKeyMatcher.find()) {
String privateKeyContent = privateKeyMatcher.group(1).replace(NEW_LINE, EMPTY).trim();
byte[] decodedPrivateKeyContent = Base64.getDecoder().decode(privateKeyContent);
keySpec = new PKCS8EncodedKeySpec(decodedPrivateKeyContent);
}

privateKeyMatcher = RSA_PRIVATE_KEY_PATTERN.matcher(identityContent);
if (privateKeyMatcher.find()) {
String privateKeyContent = privateKeyMatcher.group(1).replace(NEW_LINE, EMPTY).trim();
byte[] decodedPrivateKeyContent = Base64.getDecoder().decode(privateKeyContent);
keySpec = getKeySpecFromAsn1StructuredData(decodedPrivateKeyContent);
}

privateKeyMatcher = ENCRYPTED_PRIVATE_KEY_PATTERN.matcher(identityContent);
if (privateKeyMatcher.find()) {
String privateKeyContent = privateKeyMatcher.group(1).replace(NEW_LINE, EMPTY).trim();
byte[] decodedPrivateKeyContent = Base64.getDecoder().decode(privateKeyContent);
keySpec = null; //TODO
}

Objects.requireNonNull(keySpec);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
return keyFactory.generatePrivate(keySpec);
}

private static KeySpec getKeySpecFromAsn1StructuredData(byte[] decodedPrivateKeyContent) throws IOException {
try(ByteArrayInputStream privateKeyAsInputStream = new ByteArrayInputStream(decodedPrivateKeyContent)) {
ASN1InputStream stream = new ASN1InputStream(new DERDecoder(), privateKeyAsInputStream);
ASN1Sequence asn1Sequence = stream.readObject();

if (asn1Sequence.getValue().size() < 9) {
throw new RuntimeException("Parsed key content doesn't have the minimum required sequence size of 9");
}

BigInteger modulus = extractIntValueFrom(asn1Sequence.get(1));
BigInteger publicExponent = extractIntValueFrom(asn1Sequence.get(2));
BigInteger privateExponent = extractIntValueFrom(asn1Sequence.get(3));
BigInteger primeP = extractIntValueFrom(asn1Sequence.get(4));
BigInteger primeQ = extractIntValueFrom(asn1Sequence.get(5));
BigInteger primeExponentP = extractIntValueFrom(asn1Sequence.get(6));
BigInteger primeExponentQ = extractIntValueFrom(asn1Sequence.get(7));
BigInteger crtCoefficient = extractIntValueFrom(asn1Sequence.get(8));

return new RSAPrivateCrtKeySpec(
modulus, publicExponent, privateExponent,
primeP, primeQ, primeExponentP, primeExponentQ, crtCoefficient
);
}
}

private static BigInteger extractIntValueFrom(ASN1Object asn1Object) {
if (asn1Object instanceof ASN1Integer) {
return ((ASN1Integer) asn1Object).getValue();
} else {
throw new RuntimeException(String.format(
"Unable to parse the provided value of the object type [%s]. The type should be an instance of [%s]",
asn1Object.getClass().getName(), ASN1Integer.class.getName())
);
}
}

private static Map parseCertificate(String certificateContent) throws IOException, CertificateException {
Map certificates = new HashMap();
Matcher certificateMatcher = CERTIFICATE_PATTERN.matcher(certificateContent);

while (certificateMatcher.find()) {
String sanitizedCertificate = certificateMatcher.group(1).replace(NEW_LINE, EMPTY).trim();
byte[] decodedCertificate = Base64.getDecoder().decode(sanitizedCertificate);
try(ByteArrayInputStream certificateAsInputStream = new ByteArrayInputStream(decodedCertificate)) {
CertificateFactory certificateFactory = CertificateFactory.getInstance(CERTIFICATE_TYPE);
Certificate certificate = certificateFactory.generateCertificate(certificateAsInputStream);
certificates.put(UUID.randomUUID().toString(), certificate);
}
}

return certificates;
}

}
< /code>
Я также должен обрабатывать кодированный закрытый ключ ASN.1. Я мог бы использовать Bouncycastle, но я снова хотел избежать этого, потому что мне любопытно для альтернативы. Я был вдохновлен по этой теме: https://stackoverflow.com/a/42733858/6777695, но DerinputStream и Dervalue больше не доступны от JDK 11. И пакеты солнца следует избегать ... поэтому я обнаружил, что библиотека Java Asn-One Java для разбора ASN.1, кодируемого закрытого ключа, и это работает довольно хорошо. Следующий заголовок/нижний колонтитул: ----- Начните зашифрованный закрытый закрытый ключ ----- * ----- Конец зашифрованного закрытого ключа ----- также является закодированным закрытым ключом ASN.1 со следующей структурой:
EncryptedPrivateKeyInfo ::= SEQUENCE {
encryptionAlgorithm EncryptionAlgorithmIdentifier,
encryptedData EncryptedData
}

EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier

EncryptedData ::= OCTET STRING
< /code>
Я также попробовал ответы, предоставленные здесь, как прочитать зашифрованный пароль с Java? Но они также не работали. Однако я не совсем уверен, как правильно проанализировать его в Java -объект и загрузить его как KeySpec. Так что любая справка приветствуется! < /P>
======>
Обновленный прогресс в 12-09-2020 на основе ввода Dave_thompson_085 < /code> < /p>
Matcher privateKeyMatcher = Pattern.compile("-----BEGIN ENCRYPTED PRIVATE KEY-----(.*?)-----END ENCRYPTED PRIVATE KEY-----", Pattern.DOTALL)
.matcher(identityContent);

if (privateKeyMatcher.find()) {
String privateKeyContent = privateKeyMatcher.group(1).replace(NEW_LINE, EMPTY).trim();
byte[] decodedPrivateKeyContent = Base64.getDecoder().decode(privateKeyContent);
try (ByteArrayInputStream privateKeyAsInputStream = new ByteArrayInputStream(decodedPrivateKeyContent)) {
ASN1InputStream stream = new ASN1InputStream(new DERDecoder(), privateKeyAsInputStream);
ASN1Sequence asn1Sequence = stream.readObject();

ASN1OctetString privateKeyAsOctetString = (ASN1OctetString) asn1Sequence.get(1);
ASN1OctetString saltAsOctetString = (ASN1OctetString) ((ASN1Sequence) ((ASN1Sequence) ((ASN1Sequence) ((ASN1Sequence) asn1Sequence.get(0)).get(1)).get(0)).get(1)).get(0);
ASN1OctetString initializationVectorAsOctec = ((ASN1OctetString) ((ASN1Sequence) ((ASN1Sequence) ((ASN1Sequence) asn1Sequence.get(0)).get(1)).get(1)).get(1));
ASN1Integer iterationCount = (ASN1Integer) ((ASN1Sequence) ((ASN1Sequence) ((ASN1Sequence) ((ASN1Sequence) asn1Sequence.get(0)).get(1)).get(0)).get(1)).get(1);

IvParameterSpec ivParameterSpec = new IvParameterSpec(initializationVectorAsOctec.getValue());

SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2withHmacSHA1");
EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(secretKeyFactory.getAlgorithm(), privateKeyAsOctetString.getValue());

int keyLength = encryptedPrivateKeyInfo.getEncoded().length;
PBEKeySpec pbeKeySpec = new PBEKeySpec(keyPassword, saltAsOctetString.getValue(), iterationCount.getValue().intValue(), keyLength);

Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding/");

SecretKey secretKey = secretKeyFactory.generateSecret(pbeKeySpec);

cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
PKCS8EncodedKeySpec keySpec = encryptedPrivateKeyInfo.getKeySpec(cipher);
}
}

Результаты в следующем исключении: java.security.invalidkeyexception: Неправильный алгоритм: Deseed или Tripledes. 13-09-2020 на основе ввода Майкла Фера
Matcher privateKeyMatcher = Pattern.compile("-----BEGIN ENCRYPTED PRIVATE KEY-----(.*?)-----END ENCRYPTED PRIVATE KEY-----", Pattern.DOTALL)
.matcher(identityContent);

if (privateKeyMatcher.find()) {
String privateKeyContent = privateKeyMatcher.group(1).replace(NEW_LINE, EMPTY).trim();
byte[] decodedPrivateKeyContent = Base64.getDecoder().decode(privateKeyContent);
try (ByteArrayInputStream privateKeyAsInputStream = new ByteArrayInputStream(decodedPrivateKeyContent)) {
ASN1InputStream stream = new ASN1InputStream(new DERDecoder(), privateKeyAsInputStream);
ASN1Sequence asn1Sequence = stream.readObject();

ASN1OctetString privateKeyAsOctetString = (ASN1OctetString) asn1Sequence.get(1);
ASN1OctetString saltAsOctetString = (ASN1OctetString) ((ASN1Sequence) ((ASN1Sequence) ((ASN1Sequence) ((ASN1Sequence) asn1Sequence.get(0)).get(1)).get(0)).get(1)).get(0);
ASN1OctetString initializationVectorAsOctec = ((ASN1OctetString) ((ASN1Sequence) ((ASN1Sequence) ((ASN1Sequence) asn1Sequence.get(0)).get(1)).get(1)).get(1));
ASN1Integer iterationCount = (ASN1Integer) ((ASN1Sequence) ((ASN1Sequence) ((ASN1Sequence) ((ASN1Sequence) asn1Sequence.get(0)).get(1)).get(0)).get(1)).get(1);

IvParameterSpec ivParameterSpec = new IvParameterSpec(initializationVectorAsOctec.getValue());

SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2withHmacSHA1");
EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(secretKeyFactory.getAlgorithm(), privateKeyAsOctetString.getValue());

int keyLength = 24 * 8;
PBEKeySpec pbeKeySpec = new PBEKeySpec(keyPassword, saltAsOctetString.getValue(), iterationCount.getValue().intValue(), keyLength);

Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding/");

SecretKey secretKeyPbkdf = secretKeyFactory.generateSecret(pbeKeySpec);
SecretKey secretKey = new SecretKeySpec(secretKeyPbkdf.getEncoded(), "DESede");

cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
PKCS8EncodedKeySpec keySpec = encryptedPrivateKeyInfo.getKeySpec(cipher);
}
}


Подробнее здесь: https://stackoverflow.com/questions/638 ... amatically
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»