Last active
February 9, 2022 00:11
-
-
Save markscottwright/ec0b1b7418e70aa5d884cacc7e4a22af to your computer and use it in GitHub Desktop.
How to use an SSH2 key in Java.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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