]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.core/src/org/argeo/ssh/SshKeyPair.java
Support regular and SWT CSS in CMS Theme.
[lgpl/argeo-commons.git] / org.argeo.core / src / org / argeo / ssh / SshKeyPair.java
1 package org.argeo.ssh;
2
3 import java.io.IOException;
4 import java.io.InputStreamReader;
5 import java.io.Reader;
6 import java.io.StringReader;
7 import java.io.StringWriter;
8 import java.nio.charset.StandardCharsets;
9 import java.nio.file.Files;
10 import java.nio.file.Path;
11 import java.nio.file.Paths;
12 import java.security.GeneralSecurityException;
13 import java.security.KeyFactory;
14 import java.security.KeyPair;
15 import java.security.PrivateKey;
16 import java.security.PublicKey;
17 import java.security.interfaces.RSAPrivateCrtKey;
18 import java.security.spec.RSAPublicKeySpec;
19
20 import org.apache.sshd.common.config.keys.KeyUtils;
21 import org.apache.sshd.common.config.keys.PublicKeyEntry;
22 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
23 import org.bouncycastle.openssl.PEMKeyPair;
24 import org.bouncycastle.openssl.PEMParser;
25 import org.bouncycastle.openssl.PKCS8Generator;
26 import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
27 import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
28 import org.bouncycastle.openssl.jcajce.JcaPKCS8Generator;
29 import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
30 import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder;
31 import org.bouncycastle.operator.InputDecryptorProvider;
32 import org.bouncycastle.operator.OutputEncryptor;
33 import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
34
35 @SuppressWarnings("restriction")
36 public class SshKeyPair {
37 public final static String RSA_KEY_TYPE = "ssh-rsa";
38
39 private PublicKey publicKey;
40 private PrivateKey privateKey;
41 private KeyPair keyPair;
42
43 public SshKeyPair(KeyPair keyPair) {
44 super();
45 this.publicKey = keyPair.getPublic();
46 this.privateKey = keyPair.getPrivate();
47 this.keyPair = keyPair;
48 }
49
50 public SshKeyPair(PublicKey publicKey, PrivateKey privateKey) {
51 super();
52 this.publicKey = publicKey;
53 this.privateKey = privateKey;
54 this.keyPair = new KeyPair(publicKey, privateKey);
55 }
56
57 public KeyPair asKeyPair() {
58 return keyPair;
59 }
60
61 public String getPublicKeyAsOpenSshString() {
62 return PublicKeyEntry.toString(publicKey);
63 }
64
65 public String getPrivateKeyAsPemString(char[] password) {
66 try {
67 Object obj;
68
69 if (password != null) {
70 JceOpenSSLPKCS8EncryptorBuilder encryptorBuilder = new JceOpenSSLPKCS8EncryptorBuilder(
71 PKCS8Generator.PBE_SHA1_3DES);
72 encryptorBuilder.setPasssword(password);
73 OutputEncryptor oe = encryptorBuilder.build();
74 JcaPKCS8Generator gen = new JcaPKCS8Generator(privateKey, oe);
75 obj = gen.generate();
76 } else {
77 obj = privateKey;
78 }
79
80 StringWriter sw = new StringWriter();
81 JcaPEMWriter pemWrt = new JcaPEMWriter(sw);
82 pemWrt.writeObject(obj);
83 pemWrt.close();
84 return sw.toString();
85 } catch (Exception e) {
86 throw new RuntimeException("Cannot convert private key", e);
87 }
88 }
89
90 public static SshKeyPair loadOrGenerate(Path privateKeyPath, int size, char[] password) {
91 try {
92 SshKeyPair sshKeyPair;
93 if (Files.exists(privateKeyPath)) {
94 // String privateKeyStr = new String(Files.readAllBytes(privateKeyPath), StandardCharsets.US_ASCII);
95 sshKeyPair = load(
96 new InputStreamReader(Files.newInputStream(privateKeyPath), StandardCharsets.US_ASCII),
97 password);
98 // TOD make sure public key is consistemt
99 } else {
100 sshKeyPair = generate(size);
101 Files.write(privateKeyPath,
102 sshKeyPair.getPrivateKeyAsPemString(password).getBytes(StandardCharsets.US_ASCII));
103 Path publicKeyPath = privateKeyPath.resolveSibling(privateKeyPath.getFileName() + ".pub");
104 Files.write(publicKeyPath,
105 sshKeyPair.getPublicKeyAsOpenSshString().getBytes(StandardCharsets.US_ASCII));
106 }
107 return sshKeyPair;
108 } catch (IOException e) {
109 throw new RuntimeException("Cannot read or write private key " + privateKeyPath, e);
110 }
111 }
112
113 public static SshKeyPair generate(int size) {
114 return generate(RSA_KEY_TYPE, size);
115 }
116
117 public static SshKeyPair generate(String keyType, int size) {
118 try {
119 KeyPair keyPair = KeyUtils.generateKeyPair(keyType, size);
120 PublicKey publicKey = keyPair.getPublic();
121 PrivateKey privateKey = keyPair.getPrivate();
122 return new SshKeyPair(publicKey, privateKey);
123 } catch (GeneralSecurityException e) {
124 throw new RuntimeException("Cannot generate SSH key", e);
125 }
126 }
127
128 public static SshKeyPair load(Reader reader, char[] password) {
129 try (PEMParser pemParser = new PEMParser(reader)) {
130 Object object = pemParser.readObject();
131 JcaPEMKeyConverter converter = new JcaPEMKeyConverter();// .setProvider("BC");
132 KeyPair kp;
133 if (object instanceof PKCS8EncryptedPrivateKeyInfo) {
134 // Encrypted key - we will use provided password
135 PKCS8EncryptedPrivateKeyInfo ckp = (PKCS8EncryptedPrivateKeyInfo) object;
136 // PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password);
137 InputDecryptorProvider inputDecryptorProvider = new JceOpenSSLPKCS8DecryptorProviderBuilder()
138 .build(password);
139 PrivateKeyInfo pkInfo = ckp.decryptPrivateKeyInfo(inputDecryptorProvider);
140 PrivateKey privateKey = converter.getPrivateKey(pkInfo);
141
142 // generate public key
143 RSAPrivateCrtKey privk = (RSAPrivateCrtKey) privateKey;
144 RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(privk.getModulus(),
145 privk.getPublicExponent());
146 KeyFactory keyFactory = KeyFactory.getInstance("RSA");
147 PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
148
149 kp = new KeyPair(publicKey, privateKey);
150 } else {
151 // Unencrypted key - no password needed
152 // PKCS8EncryptedPrivateKeyInfo ukp = (PKCS8EncryptedPrivateKeyInfo) object;
153 PEMKeyPair pemKp = (PEMKeyPair) object;
154 kp = converter.getKeyPair(pemKp);
155 }
156 return new SshKeyPair(kp);
157 } catch (Exception e) {
158 throw new RuntimeException("Cannot load private key", e);
159 }
160 }
161
162 public static void main(String args[]) {
163 Path privateKeyPath = Paths.get(System.getProperty("user.dir") + "/id_rsa");
164 SshKeyPair skp = SshKeyPair.loadOrGenerate(privateKeyPath, 1024, null);
165 System.out.println("Public:\n" + skp.getPublicKeyAsOpenSshString());
166 System.out.println("Private (plain):\n" + skp.getPrivateKeyAsPemString(null));
167 System.out.println("Private (encrypted):\n" + skp.getPrivateKeyAsPemString("demo".toCharArray()));
168
169 StringReader reader = new StringReader(skp.getPrivateKeyAsPemString(null));
170 skp = SshKeyPair.load(reader, null);
171 System.out.println("Public:\n" + skp.getPublicKeyAsOpenSshString());
172 System.out.println("Private (plain):\n" + skp.getPrivateKeyAsPemString(null));
173 System.out.println("Private (encrypted):\n" + skp.getPrivateKeyAsPemString("demo".toCharArray()));
174
175 reader = new StringReader(skp.getPrivateKeyAsPemString("demo".toCharArray()));
176 skp = SshKeyPair.load(reader, "demo".toCharArray());
177 System.out.println("Public:\n" + skp.getPublicKeyAsOpenSshString());
178 System.out.println("Private (plain):\n" + skp.getPrivateKeyAsPemString(null));
179 System.out.println("Private (encrypted):\n" + skp.getPrivateKeyAsPemString("demo".toCharArray()));
180 }
181
182 }