Skip to content

Instantly share code, notes, and snippets.

@markscottwright
Last active February 9, 2022 00:11
Show Gist options
  • Save markscottwright/ec0b1b7418e70aa5d884cacc7e4a22af to your computer and use it in GitHub Desktop.
Save markscottwright/ec0b1b7418e70aa5d884cacc7e4a22af to your computer and use it in GitHub Desktop.
How to use an SSH2 key in Java.
import static org.bouncycastle.crypto.util.OpenSSHPrivateKeyUtil.parsePrivateKeyBlob;
import java.io.IOException;
import java.io.StringReader;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPublicKeySpec;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.util.io.pem.PemReader;
/**
* Note that this requires bouncy castle 1.71. Currently on https://downloads.bouncycastle.org/betas/.
* The key below was generated using `ssh-keygen -f tempkey`.
*/
public class Main {
public static void main(String[] args) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException,
InvalidKeyException, SignatureException {
StringReader reader = new StringReader("-----BEGIN OPENSSH PRIVATE KEY-----\r\n"
+ "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\r\n" + "-----END OPENSSH PRIVATE KEY-----\r\n");
byte[] blob = new PemReader(reader).readPemObject().getContent();
var privateKeyParams = (RSAPrivateCrtKeyParameters) parsePrivateKeyBlob(blob);
// @formatter:off
var keySpec = new RSAPrivateCrtKeySpec(
privateKeyParams.getModulus(),
privateKeyParams.getPublicExponent(),
privateKeyParams.getExponent(),
privateKeyParams.getP(),
privateKeyParams.getQ(),
privateKeyParams.getDP(),
privateKeyParams.getDQ(),
privateKeyParams.getQInv());
// @formatter:on
var publicKeySpec = new RSAPublicKeySpec(privateKeyParams.getModulus(), privateKeyParams.getPublicExponent());
var privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
var publicKey = KeyFactory.getInstance("RSA").generatePublic(publicKeySpec);
{
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initSign(privateKey);
signer.update("Some data".getBytes());
byte[] signature = signer.sign();
Signature verifier = Signature.getInstance("SHA256withRSA");
verifier.initVerify(publicKey);
verifier.update("Some data".getBytes());
boolean verified = verifier.verify(signature);
System.out.println(verified);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment