Как преобразовать ECPrivateKey в формат OpenSSH, закодированный в PEM?JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Как преобразовать ECPrivateKey в формат OpenSSH, закодированный в PEM?

Сообщение Anonymous »

Учитывая этот случайно сгенерированный закрытый ключ ECDSA:

Код: Выделить всё

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQR1n1SFvy7Di392GmMy8JsWEjbffTCu
nGKwZrIgq/yIy1C33ud4bxN3W4vbXCtZfyPeVbWNpW1eXSZ/3uWmcJ3SAAAAmCxLaSMsS2
kjAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHWfVIW/LsOLf3Ya
YzLwmxYSNt99MK6cYrBmsiCr/IjLULfe53hvE3dbi9tcK1l/I95VtY2lbV5dJn/e5aZwnd
IAAAAgUgu0f1JX6BTUL3UU3Xq3C8erF/W2cIgzuCHciLp55HYAAAAA
-----END OPENSSH PRIVATE KEY-----
Я использую этот код для преобразования его в PrivateKey:

Код: Выделить всё

public PrivateKey readPrivateKeyAsOpenSsh(Reader reader) throws IOException
{
try (PemReader pemReader = new PemReader(reader))
{
PemObject pemObject = pemReader.readPemObject();
byte[] content = pemObject.getContent();
AsymmetricKeyParameter keyParameter = OpenSSHPrivateKeyUtil.parsePrivateKeyBlob(content);
if (!(keyParameter instanceof ECPrivateKeyParameters ecPrivateKeyParameters))
throw new UnsupportedOperationException("Unsupported format: " + pemObject.getType());
BigInteger d = ecPrivateKeyParameters.getD();
ECNamedCurveSpec ecNamedCurveSpec = getEcNamedCurveSpec(ecPrivateKeyParameters);
ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d, ecNamedCurveSpec);
KeyFactory keyFactory;
try
{
keyFactory = KeyFactory.getInstance("EC");
return keyFactory.generatePrivate(ecPrivateKeySpec);
}
catch (NoSuchAlgorithmException | InvalidKeySpecException e)
{
// Deployment-type decision
throw new AssertionError(e);
}
}
}

/**
* Returns the name of a key's algorithm.
*
* @param keyParameter a key's parameters
* @return the name of the key's algorithm
* @throws IOException if the algorithm is unsupported
*/
private static String getAlgorithm(AsymmetricKeyParameter keyParameter) throws IOException
{
return switch (keyParameter)
{
case RSAKeyParameters _ -> "RSA";
case DSAPublicKeyParameters _ -> "DSA";
case ECPublicKeyParameters _ -> "EC";
default -> throw new IOException("Unsupported key parameter: " +
keyParameter.getClass().getName());
};
}

/**
* @param keyParameters the private key's parameters
* @return the set of domain parameters used with elliptic curve cryptography (ECC)
* @throws IOException if the elliptical curve used is unknown
*/
private ECNamedCurveSpec getEcNamedCurveSpec(ECPrivateKeyParameters keyParameters) throws IOException
{
ECDomainParameters domainParameters = keyParameters.getParameters();
X9ECParameters x9ECParameters = getX9EcParameters(domainParameters);
if (x9ECParameters == null)
throw new IOException("Failed to convert domain parameters to X9ECParameters");

EllipticCurve ellipticCurve = new EllipticCurve(
new ECFieldFp(x9ECParameters.getCurve().getField().getCharacteristic()),
x9ECParameters.getCurve().getA().toBigInteger(),
x9ECParameters.getCurve().getB().toBigInteger());
ECPoint g = x9ECParameters.getG();

String curveName = getCurveName(domainParameters);
if (curveName == null)
throw new IOException("Failed to find the curve name");
return new ECNamedCurveSpec(curveName,
ellipticCurve,
new java.security.spec.ECPoint(
g.getAffineXCoord().toBigInteger(),
g.getAffineYCoord().toBigInteger()),
x9ECParameters.getN(),
x9ECParameters.getH());
}

/**
* Returns the X9ECParameters of the curve with the specified domain parameters.
*
* @param domainParameters domain parameters
* @return null if no match is found
*/
private X9ECParameters getX9EcParameters(ECDomainParameters domainParameters)
{
Entry details = getCurveDetails(domainParameters);
if (details == null)
return null;
return details.getValue();
}

/**
* Returns the name of the curve with the specified domain parameters.
*
* @param domainParameters domain parameters
* @return null if no match is found
*/
private String getCurveName(ECDomainParameters domainParameters)
{
Entry  details = getCurveDetails(domainParameters);
if (details == null)
return null;
return details.getKey();
}

/**
* Returns the name and X9ECParameters of the curve with the specified domain parameters.
*
* @param domainParameters domain parameters
* @return null if no match is found
*/
private Entry getCurveDetails(ECDomainParameters domainParameters)
{
for (Enumeration e = ECNamedCurveTable.getNames(); e.hasMoreElements(); )
{
String name = (String) e.nextElement();
X9ECParameters x9EcParams = ECNamedCurveTable.getByName(name);
if (x9EcParams.getCurve().equals(domainParameters.getCurve()))
return new SimpleImmutableEntry(name, x9EcParams);
}
return null;
}
Кажется, это работает, но я не могу понять, как преобразовать его обратно в закодированный в PEM ЗАКРЫТЫЙ КЛЮЧ OPENSSH. Вот код, который не работает:

Код: Выделить всё

/**
* Writes a {@code PrivateKey} as a PEM-encoded OpenSSH format stream.
*
* @param privateKey the key
* @param writer     the stream to write into
* @throws NullPointerException if any of the arguments are null
* @throws IOException          if an error occurs while writing into the stream
*/
public void writePrivateKeyAsOpenSsh(ECPrivateKey privateKey, Writer writer) throws IOException
{
AsymmetricKeyParameter param = getAsymmetricKeyParameter(privateKey);
try (JcaPEMWriter pemWriter = new JcaPEMWriter(writer))
{
byte[] encodedPrivateKey = OpenSSHPrivateKeyUtil.encodePrivateKey(param);
PemObject pemObject = new PemObject("OPENSSH PRIVATE KEY", encodedPrivateKey);
pemWriter.writeObject(pemObject);
pemWriter.flush();
}
}
Он возвращает следующий результат:

Код: Выделить всё

-----BEGIN OPENSSH PRIVATE KEY-----
MIIBaAIBAQQgUgu0f1JX6BTUL3UU3Xq3C8erF/W2cIgzuCHciLp55HaggfowgfcC
AQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAAAAAAAAAAAAAA////////////////
MFsEIP////8AAAABAAAAAAAAAAAAAAAA///////////////8BCBaxjXYqjqT57Pr
vVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSdNgiG5wSTamZ44ROdJreBn36QBEEE
axfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54W
K84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8
YyVRAgEBoUQDQgAEdZ9Uhb8uw4t/dhpjMvCbFhI2330wrpxisGayIKv8iMtQt97n
eG8Td1uL21wrWX8j3lW1jaVtXl0mf97lpnCd0g==
-----END OPENSSH PRIVATE KEY-----
который, похоже, не является действительным ключом. Я безуспешно ищу дискуссионные форумы и тестовые примеры BouncyCastle.
Есть идеи?
  • Если есть более простой способ для анализа исходного ввода дайте мне знать.
  • Не предлагайте использовать другие библиотеки, кроме JCA или BouncyCastle, если нет другого способа.
    Спасибо за заранее.

    Подробнее здесь: https://stackoverflow.com/questions/792 ... ssh-format
Ответить

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

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

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

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

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