diff --git a/.gitignore b/.gitignore index 193e3e43..5b05e0d1 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,9 @@ # Output dirs target/ build/ +docs/ .gradle/ +sshj.jar - +# MacOS X +.DS_Store diff --git a/src/main/java/net/schmizz/sshj/common/StreamCopier.java b/src/main/java/net/schmizz/sshj/common/StreamCopier.java index 957ce796..18e228de 100644 --- a/src/main/java/net/schmizz/sshj/common/StreamCopier.java +++ b/src/main/java/net/schmizz/sshj/common/StreamCopier.java @@ -107,7 +107,7 @@ public class StreamCopier { log.debug("Done copying from {}", in); doneEvent.set(); } catch (IOException ioe) { - log.error("In pipe from {} to {}: {}", in, out, ioe); + log.error(String.format("In pipe from %1$s to %2$s", in.toString(), out.toString()), ioe); doneEvent.deliverError(ioe); } } @@ -136,7 +136,7 @@ public class StreamCopier { final double timeSeconds = (System.currentTimeMillis() - startTime) / 1000.0; final double sizeKiB = count / 1024.0; - log.debug("{} KiB transferred in {} seconds ({} KiB/s)", sizeKiB, timeSeconds, (sizeKiB / timeSeconds)); + log.debug(String.format("%1$,.1f KiB transferred in %2$,.1f seconds (%3$,.2f KiB/s)", sizeKiB, timeSeconds, (sizeKiB / timeSeconds))); if (length != -1 && read == -1) throw new IOException("Encountered EOF, could not transfer " + length + " bytes"); diff --git a/src/main/java/net/schmizz/sshj/transport/verification/OpenSSHKnownHosts.java b/src/main/java/net/schmizz/sshj/transport/verification/OpenSSHKnownHosts.java index b74131eb..78500b59 100644 --- a/src/main/java/net/schmizz/sshj/transport/verification/OpenSSHKnownHosts.java +++ b/src/main/java/net/schmizz/sshj/transport/verification/OpenSSHKnownHosts.java @@ -262,6 +262,13 @@ public class OpenSSHKnownHosts } public interface HostEntry { + KeyType getType(); + + String getFingerprint(); + + boolean appliesTo(String host) + throws IOException; + boolean appliesTo(KeyType type, String host) throws IOException; @@ -279,6 +286,22 @@ public class OpenSSHKnownHosts this.comment = comment; } + @Override + public KeyType getType() { + return KeyType.UNKNOWN; + } + + @Override + public String getFingerprint() { + return null; + } + + @Override + public boolean appliesTo(String host) + throws IOException { + return false; + } + @Override public boolean appliesTo(KeyType type, String host) { return false; @@ -308,6 +331,16 @@ public class OpenSSHKnownHosts this.key = key; } + @Override + public KeyType getType() { + return type; + } + + @Override + public String getFingerprint() { + return SecurityUtils.getFingerprint(key); + } + @Override public boolean verify(PublicKey key) throws IOException { @@ -349,6 +382,12 @@ public class OpenSSHKnownHosts return hostnames; } + @Override + public boolean appliesTo(String host) + throws IOException { + return hosts.contains(host); + } + @Override public boolean appliesTo(KeyType type, String host) throws IOException { @@ -377,6 +416,12 @@ public class OpenSSHKnownHosts } } + @Override + public boolean appliesTo(String host) + throws IOException { + return hashedHost.equals(hashHost(host)); + } + @Override public boolean appliesTo(KeyType type, String host) throws IOException { @@ -426,4 +471,4 @@ public class OpenSSHKnownHosts } -} \ No newline at end of file +} diff --git a/src/main/java/net/schmizz/sshj/userauth/keyprovider/KeyFormat.java b/src/main/java/net/schmizz/sshj/userauth/keyprovider/KeyFormat.java index cc1a5b44..816b2bd8 100644 --- a/src/main/java/net/schmizz/sshj/userauth/keyprovider/KeyFormat.java +++ b/src/main/java/net/schmizz/sshj/userauth/keyprovider/KeyFormat.java @@ -19,6 +19,7 @@ package net.schmizz.sshj.userauth.keyprovider; * @version $Id:$ */ public enum KeyFormat { + PKCS5, PKCS8, OpenSSH, PuTTY, diff --git a/src/main/java/net/schmizz/sshj/userauth/keyprovider/KeyProviderUtil.java b/src/main/java/net/schmizz/sshj/userauth/keyprovider/KeyProviderUtil.java index 4e897825..b6f8a8c4 100644 --- a/src/main/java/net/schmizz/sshj/userauth/keyprovider/KeyProviderUtil.java +++ b/src/main/java/net/schmizz/sshj/userauth/keyprovider/KeyProviderUtil.java @@ -96,9 +96,10 @@ public class KeyProviderUtil { if (separatePubKey) { // Can delay asking for password since have unencrypted pubkey return KeyFormat.OpenSSH; - } else { - // More general + } else if (header.indexOf("BEGIN PRIVATE KEY") != -1 || header.indexOf("BEGIN ENCRYPTED PRIVATE KEY") != -1) { return KeyFormat.PKCS8; + } else { + return KeyFormat.PKCS5; } } else if (header.startsWith("PuTTY-User-Key-File-")) { return KeyFormat.PuTTY; diff --git a/src/main/java/net/schmizz/sshj/userauth/keyprovider/PKCS5KeyFile.java b/src/main/java/net/schmizz/sshj/userauth/keyprovider/PKCS5KeyFile.java new file mode 100644 index 00000000..736b78da --- /dev/null +++ b/src/main/java/net/schmizz/sshj/userauth/keyprovider/PKCS5KeyFile.java @@ -0,0 +1,309 @@ +/* + * Copyright (C)2009 - SSHJ Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.schmizz.sshj.userauth.keyprovider; + +import net.schmizz.sshj.common.Base64; +import net.schmizz.sshj.common.IOUtils; +import net.schmizz.sshj.common.KeyType; +import net.schmizz.sshj.transport.cipher.AES128CBC; +import net.schmizz.sshj.transport.cipher.AES192CBC; +import net.schmizz.sshj.transport.cipher.AES256CBC; +import net.schmizz.sshj.transport.cipher.Cipher; +import net.schmizz.sshj.transport.cipher.NoneCipher; +import net.schmizz.sshj.transport.cipher.TripleDESCBC; +import net.schmizz.sshj.transport.digest.Digest; +import net.schmizz.sshj.transport.digest.MD5; +import net.schmizz.sshj.userauth.password.PasswordFinder; +import net.schmizz.sshj.userauth.password.PasswordUtils; +import net.schmizz.sshj.userauth.password.PrivateKeyFileResource; +import net.schmizz.sshj.userauth.password.PrivateKeyReaderResource; +import net.schmizz.sshj.userauth.password.PrivateKeyStringResource; +import net.schmizz.sshj.userauth.password.Resource; + +import java.io.BufferedReader; +import java.io.File; +import java.io.EOFException; +import java.io.IOException; +import java.io.Reader; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.DSAPrivateKeySpec; +import java.security.spec.DSAPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.RSAPrivateKeySpec; +import java.security.spec.RSAPublicKeySpec; +import java.util.Arrays; +import javax.xml.bind.DatatypeConverter; + +/** Represents a PKCS5-encoded key file. This is the format typically used by OpenSSH, OpenSSL, Amazon, etc. */ +public class PKCS5KeyFile + implements FileKeyProvider { + + public static class Factory + implements net.schmizz.sshj.common.Factory.Named { + + @Override + public FileKeyProvider create() { + return new PKCS5KeyFile(); + } + + @Override + public String getName() { + return "PKCS5"; + } + } + + protected PasswordFinder pwdf; + protected Resource resource; + protected KeyPair kp; + + protected KeyType type; + + protected char[] passphrase; // for blanking out + + @Override + public PrivateKey getPrivate() + throws IOException { + return kp != null ? kp.getPrivate() : (kp = readKeyPair()).getPrivate(); + } + + @Override + public PublicKey getPublic() + throws IOException { + return kp != null ? kp.getPublic() : (kp = readKeyPair()).getPublic(); + } + + @Override + public KeyType getType() + throws IOException { + return type != null ? type : (type = KeyType.fromKey(getPublic())); + } + + @Override + public void init(Reader location) { + assert location != null; + resource = new PrivateKeyReaderResource(location); + } + + @Override + public void init(Reader location, PasswordFinder pwdf) { + init(location); + this.pwdf = pwdf; + } + + @Override + public void init(File location) { + assert location != null; + resource = new PrivateKeyFileResource(location.getAbsoluteFile()); + } + + @Override + public void init(File location, PasswordFinder pwdf) { + init(location); + this.pwdf = pwdf; + } + + @Override + public void init(String privateKey, String publicKey) { + assert privateKey != null; + assert publicKey == null; + resource = new PrivateKeyStringResource(privateKey); + } + + @Override + public void init(String privateKey, String publicKey, PasswordFinder pwdf) { + init(privateKey, publicKey); + this.pwdf = pwdf; + } + + protected KeyPair readKeyPair() + throws IOException { + BufferedReader reader = new BufferedReader(resource.getReader()); + try { + String type = null; + String line = null; + Cipher cipher = new NoneCipher(); + StringBuffer sb = new StringBuffer(); + byte[] iv = new byte[0]; // salt + while ((line = reader.readLine()) != null) { + if (line.startsWith("-----BEGIN ") && line.endsWith(" PRIVATE KEY-----")) { + int end = line.length() - 17; + if (end > 11) { + type = line.substring(11, line.length() - 17); + } else { + type = "UNKNOWN"; + } + } else if (line.startsWith("-----END")) { + break; + } else if (type != null) { + if (line.startsWith("Proc-Type: ")) { + if (!"4,ENCRYPTED".equals(line.substring(11))) { + throw new IOException("Unrecognized Proc-Type: " + line.substring(11)); + } + } else if (line.startsWith("DEK-Info: ")) { + int ptr = line.indexOf(","); + if (ptr == -1) { + throw new IOException("Unrecognized DEK-Info: " + line.substring(10)); + } else { + String algorithm = line.substring(10,ptr); + if ("DES-EDE3-CBC".equals(algorithm)) { + cipher = new TripleDESCBC(); + iv = DatatypeConverter.parseHexBinary(line.substring(ptr+1)); + } else if ("AES-128-CBC".equals(algorithm)) { + cipher = new AES128CBC(); + iv = DatatypeConverter.parseHexBinary(line.substring(ptr+1)); + } else if ("AES-192-CBC".equals(algorithm)) { + cipher = new AES192CBC(); + iv = Base64.decode(line.substring(ptr+1)); + } else if ("AES-256-CBC".equals(algorithm)) { + cipher = new AES256CBC(); + iv = Base64.decode(line.substring(ptr+1)); + } else { + throw new IOException("Not a supported algorithm: " + algorithm); + } + } + } else if (line.length() > 0) { + sb.append(line); + } + } + } + + byte[] data = Base64.decode(sb.toString()); + if (pwdf != null) { + boolean decrypted = false; + do { + CharBuffer cb = CharBuffer.wrap(pwdf.reqPassword(resource)); + ByteBuffer bb = IOUtils.UTF8.encode(cb); + byte[] passphrase = Arrays.copyOfRange(bb.array(), bb.position(), bb.limit()); + Arrays.fill(cb.array(), '\u0000'); + Arrays.fill(bb.array(), (byte)0); + byte[] key = new byte[cipher.getBlockSize()]; + iv = Arrays.copyOfRange(iv, 0, cipher.getIVSize()); + Digest md5 = new MD5(); + md5.init(); + int hsize = md5.getBlockSize(); + byte[] hn = new byte[key.length / hsize * hsize + (key.length % hsize == 0 ? 0 : hsize)]; + byte[] tmp = null; + for (int i=0; i + hsize <= hn.length;) { + if (tmp != null) { + md5.update(tmp, 0, tmp.length); + } + md5.update(passphrase, 0, passphrase.length); + md5.update(iv, 0, iv.length > 8 ? 8 : iv.length); + tmp = md5.digest(); + System.arraycopy(tmp, 0, hn, i, tmp.length); + i += tmp.length; + } + Arrays.fill(passphrase, (byte)0); + System.arraycopy(hn, 0, key, 0, key.length); + cipher.init(Cipher.Mode.Decrypt, key, iv); + Arrays.fill(key, (byte)0); + cipher.update(data, 0, data.length); + decrypted = 0x30 == data[0]; + } while (!decrypted && pwdf.shouldRetry(resource)); + } + if (0x30 != data[0]) { + throw new IOException("Failed to decrypt key"); + } + + ASN1Data asn = new ASN1Data(data); + if ("RSA".equals(type)) { + KeyFactory factory = KeyFactory.getInstance("RSA"); + asn.readNext(); + BigInteger modulus = asn.readNext(); + BigInteger pubExp = asn.readNext(); + BigInteger prvExp = asn.readNext(); + PublicKey pubKey = factory.generatePublic(new RSAPublicKeySpec(modulus, pubExp)); + PrivateKey prvKey = factory.generatePrivate(new RSAPrivateKeySpec(modulus, prvExp)); + return new KeyPair(pubKey, prvKey); + } else if ("DSA".equals(type)) { + KeyFactory factory = KeyFactory.getInstance("DSA"); + asn.readNext(); + BigInteger p = asn.readNext(); + BigInteger q = asn.readNext(); + BigInteger g = asn.readNext(); + BigInteger pub = asn.readNext(); + BigInteger prv = asn.readNext(); + PublicKey pubKey = factory.generatePublic(new DSAPublicKeySpec(pub, p, q, g)); + PrivateKey prvKey = factory.generatePrivate(new DSAPrivateKeySpec(prv, p, q, g)); + return new KeyPair(pubKey, prvKey); + } else { + throw new IOException("Unrecognized key type: " + type); + } + } catch (NoSuchAlgorithmException e) { + throw new IOException(e); + } catch (InvalidKeySpecException e) { + throw new IOException(e); + } finally { + reader.close(); + } + } + + @Override + public String toString() { + return "PKCS5KeyFile{resource=" + resource + "}"; + } + + class ASN1Data { + private byte[] buff; + private int index, length; + + ASN1Data(byte[] buff) throws IOException { + this.buff = buff; + index = 0; + if (buff[index++] != (byte)0x30) { + throw new IOException("Not ASN.1 data"); + } + length = buff[index++] & 0xff; + if ((length & 0x80) != 0) { + int counter = length & 0x7f; + length = 0; + while (counter-- > 0) { + length = (length << 8) + (buff[index++] & 0xff); + } + } + if ((index + length) > buff.length) { + throw new IOException("Length mismatch: " + buff.length + " != " + (index + length)); + } + } + + BigInteger readNext() throws IOException { + if (index >= length) { + throw new EOFException(); + } else if (buff[index++] != 0x02) { + throw new IOException("Not an int code: " + Integer.toHexString(0xff & buff[index])); + } + int length = buff[index++] & 0xff; + if ((length & 0x80) != 0) { + int counter = length & 0x7f; + length = 0; + while (counter-- > 0) { + length = (length << 8) + (buff[index++] & 0xff); + } + } + byte[] sequence = new byte[length]; + System.arraycopy(buff, index, sequence, 0, length); + index += length; + return new BigInteger(sequence); + } + } +} diff --git a/src/test/java/net/schmizz/sshj/keyprovider/KeyProviderUtilTest.java b/src/test/java/net/schmizz/sshj/keyprovider/KeyProviderUtilTest.java index fbb64c12..36a8d345 100644 --- a/src/test/java/net/schmizz/sshj/keyprovider/KeyProviderUtilTest.java +++ b/src/test/java/net/schmizz/sshj/keyprovider/KeyProviderUtilTest.java @@ -35,6 +35,12 @@ public class KeyProviderUtilTest { assertEquals(KeyFormat.OpenSSH, format); } + @Test + public void testPkcs5() throws IOException { + KeyFormat format = KeyProviderUtil.detectKeyFileFormat(new File(ROOT, "pkcs5")); + assertEquals(KeyFormat.PKCS5, format); + } + @Test public void testPkcs8() throws IOException { KeyFormat format = KeyProviderUtil.detectKeyFileFormat(new File(ROOT, "pkcs8")); diff --git a/src/test/java/net/schmizz/sshj/keyprovider/PKCS5KeyFileTest.java b/src/test/java/net/schmizz/sshj/keyprovider/PKCS5KeyFileTest.java new file mode 100644 index 00000000..952365e2 --- /dev/null +++ b/src/test/java/net/schmizz/sshj/keyprovider/PKCS5KeyFileTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (C)2009 - SSHJ Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.schmizz.sshj.keyprovider; + +import net.schmizz.sshj.common.KeyType; +import net.schmizz.sshj.userauth.keyprovider.FileKeyProvider; +import net.schmizz.sshj.userauth.keyprovider.PKCS5KeyFile; +import net.schmizz.sshj.util.KeyUtil; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.GeneralSecurityException; + +import static org.junit.Assert.assertEquals; + +public class PKCS5KeyFileTest { + + static final FileKeyProvider rsa = new PKCS5KeyFile(); + + static final String modulus = "a19f65e93926d9a2f5b52072db2c38c54e6cf0113d31fa92ff827b0f3bec609c45ea84264c88e64adba11ff093ed48ee0ed297757654b0884ab5a7e28b3c463bc9074b32837a2b69b61d914abf1d74ccd92b20fa44db3b31fb208c0dd44edaeb4ab097118e8ee374b6727b89ad6ce43f1b70c5a437ccebc36d2dad8ae973caad15cd89ae840fdae02cae42d241baef8fda8aa6bbaa54fd507a23338da6f06f61b34fb07d560e63fbce4a39c073e28573c2962cedb292b14b80d1b4e67b0465f2be0e38526232d0a7f88ce91a055fde082038a87ed91f3ef5ff971e30ea6cccf70d38498b186621c08f8fdceb8632992b480bf57fc218e91f2ca5936770fe9469"; + static final String pubExp = "23"; + static final String privExp = "57bcee2e2656eb2c94033d802dd62d726c6705fabad1fd0df86b67600a96431301620d395cbf5871c7af3d3974dfe5c30f5c60d95d7e6e75df69ed6c5a36a9c8aef554b5058b76a719b8478efa08ad1ebf08c8c25fe4b9bc0bfbb9be5d4f60e6213b4ab1c26ad33f5bba7d93e1cd65f65f5a79eb6ebfb32f930a2b0244378b4727acf83b5fb376c38d4abecc5dc3fc399e618e792d4c745d2dbbb9735242e5033129f2985ca3e28fa33cad2afe3e70e1b07ed2b6ec8a3f843fb4bffe3385ad211c6600618488f4ac70397e8eb036b82d811283dc728504cddbe1533c4dd31b1ec99ffa74fd0e3883a9cb3e2315cc1a56f55d38ed40520dd9ec91b4d2dd790d1b"; + + @Before + public void setUp() + throws UnsupportedEncodingException, GeneralSecurityException { + rsa.init(new File("src/test/resources/id_rsa")); + } + + @Test + public void testKeys() + throws IOException, GeneralSecurityException { + assertEquals(KeyUtil.newRSAPublicKey(modulus, pubExp), rsa.getPublic()); + assertEquals(KeyUtil.newRSAPrivateKey(modulus, privExp), rsa.getPrivate()); + } + + @Test + public void testType() + throws IOException { + assertEquals(rsa.getType(), KeyType.RSA); + } + +} diff --git a/src/test/resources/keyformats/pkcs5 b/src/test/resources/keyformats/pkcs5 new file mode 100644 index 00000000..221453d8 --- /dev/null +++ b/src/test/resources/keyformats/pkcs5 @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQCm2IJ9gWDkPTlQ37NNUB0za5mCsQ8bi++8fyEqw7wl8ZNBh3qt +TcnL+m+NZfQjUC0BXic7PcMLVm4A3ID2IAZQM+axfq9aL4huWerm4ua6tvdt4gQK +oL1+8JFmdFvFw5pWW/NZHtkIprbVf7KtYrU27WmMhXruN071UzqLsw08cwIDAQAB +AoGAHQ7cOyuLSnT3RISRX8eyLkBxLffUX8HRcQzbI+2PGTSnpuQHk6NWn/Xv87pr ++LKABBr3zjOFgrX81p2QwEz3jDxNXzbOeZzhuvGXCX5GocuEO4n5EhDvXRDF4uht +uvVV5FsQv/sTOR0PNo1nELiAA8k3NYDxraB83q7wtsmErtECQQDYWMnq8mwRe49d +jIXNKJeNiuLUYxO3CLI/vx279gDKlKrt677trr1e7JZqm/DapEWG511tw3cW63gQ ++qxtgkw1AkEAxW0UeaNaJd7DApqwGAcS1JkygCKwzQ4ns/Co15qUgMkqCkmQU9AU +/zQpt2+BjdYVe50r/nr8K1KYwrBsyndrBwJBALe90N+FvFqswfoFmq2/R9eimTsg +WmIdNKYHPs2gBNQIp5MhoSpkOdkgvi8U+d33nkUQwryyQbZpjbN98mufOfECQEML +eBiW0NZrf+4yefqu7EYmgG/jWAdK91C0OaJ+bFAQAKbdtJXB5F+GZ2RUCbsRKNqB +1Z7mRRyxQA9dupRHWaECQQCM9bbCtfGesgvZlhBavlWavu8iCvJlAbGdf5QMlFQE +kABmZg84Fy3NUFCD+RXCuatb4Oo9P/WPIbjYiC4p0hLJ +-----END RSA PRIVATE KEY----- diff --git a/src/test/resources/keyformats/pkcs8 b/src/test/resources/keyformats/pkcs8 index 221453d8..29451e7a 100644 --- a/src/test/resources/keyformats/pkcs8 +++ b/src/test/resources/keyformats/pkcs8 @@ -1,15 +1,16 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQCm2IJ9gWDkPTlQ37NNUB0za5mCsQ8bi++8fyEqw7wl8ZNBh3qt -TcnL+m+NZfQjUC0BXic7PcMLVm4A3ID2IAZQM+axfq9aL4huWerm4ua6tvdt4gQK -oL1+8JFmdFvFw5pWW/NZHtkIprbVf7KtYrU27WmMhXruN071UzqLsw08cwIDAQAB -AoGAHQ7cOyuLSnT3RISRX8eyLkBxLffUX8HRcQzbI+2PGTSnpuQHk6NWn/Xv87pr -+LKABBr3zjOFgrX81p2QwEz3jDxNXzbOeZzhuvGXCX5GocuEO4n5EhDvXRDF4uht -uvVV5FsQv/sTOR0PNo1nELiAA8k3NYDxraB83q7wtsmErtECQQDYWMnq8mwRe49d -jIXNKJeNiuLUYxO3CLI/vx279gDKlKrt677trr1e7JZqm/DapEWG511tw3cW63gQ -+qxtgkw1AkEAxW0UeaNaJd7DApqwGAcS1JkygCKwzQ4ns/Co15qUgMkqCkmQU9AU -/zQpt2+BjdYVe50r/nr8K1KYwrBsyndrBwJBALe90N+FvFqswfoFmq2/R9eimTsg -WmIdNKYHPs2gBNQIp5MhoSpkOdkgvi8U+d33nkUQwryyQbZpjbN98mufOfECQEML -eBiW0NZrf+4yefqu7EYmgG/jWAdK91C0OaJ+bFAQAKbdtJXB5F+GZ2RUCbsRKNqB -1Z7mRRyxQA9dupRHWaECQQCM9bbCtfGesgvZlhBavlWavu8iCvJlAbGdf5QMlFQE -kABmZg84Fy3NUFCD+RXCuatb4Oo9P/WPIbjYiC4p0hLJ ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKbYgn2BYOQ9OVDf +s01QHTNrmYKxDxuL77x/ISrDvCXxk0GHeq1Nycv6b41l9CNQLQFeJzs9wwtWbgDc +gPYgBlAz5rF+r1oviG5Z6ubi5rq2923iBAqgvX7wkWZ0W8XDmlZb81ke2QimttV/ +sq1itTbtaYyFeu43TvVTOouzDTxzAgMBAAECgYAdDtw7K4tKdPdEhJFfx7IuQHEt +99RfwdFxDNsj7Y8ZNKem5AeTo1af9e/zumv4soAEGvfOM4WCtfzWnZDATPeMPE1f +Ns55nOG68ZcJfkahy4Q7ifkSEO9dEMXi6G269VXkWxC/+xM5HQ82jWcQuIADyTc1 +gPGtoHzervC2yYSu0QJBANhYyerybBF7j12Mhc0ol42K4tRjE7cIsj+/Hbv2AMqU +qu3rvu2uvV7slmqb8NqkRYbnXW3DdxbreBD6rG2CTDUCQQDFbRR5o1ol3sMCmrAY +BxLUmTKAIrDNDiez8KjXmpSAySoKSZBT0BT/NCm3b4GN1hV7nSv+evwrUpjCsGzK +d2sHAkEAt73Q34W8WqzB+gWarb9H16KZOyBaYh00pgc+zaAE1AinkyGhKmQ52SC+ +LxT53feeRRDCvLJBtmmNs33ya5858QJAQwt4GJbQ1mt/7jJ5+q7sRiaAb+NYB0r3 +ULQ5on5sUBAApt20lcHkX4ZnZFQJuxEo2oHVnuZFHLFAD126lEdZoQJBAIz1tsK1 +8Z6yC9mWEFq+VZq+7yIK8mUBsZ1/lAyUVASQAGZmDzgXLc1QUIP5FcK5q1vg6j0/ +9Y8huNiILinSEsk= +-----END PRIVATE KEY----- diff --git a/src/test/resources/keyformats/pkcs8-blanks b/src/test/resources/keyformats/pkcs8-blanks index b49fac32..4ed14034 100644 --- a/src/test/resources/keyformats/pkcs8-blanks +++ b/src/test/resources/keyformats/pkcs8-blanks @@ -1,18 +1,20 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQCm2IJ9gWDkPTlQ37NNUB0za5mCsQ8bi++8fyEqw7wl8ZNBh3qt -TcnL+m+NZfQjUC0BXic7PcMLVm4A3ID2IAZQM+axfq9aL4huWerm4ua6tvdt4gQK -oL1+8JFmdFvFw5pWW/NZHtkIprbVf7KtYrU27WmMhXruN071UzqLsw08cwIDAQAB -AoGAHQ7cOyuLSnT3RISRX8eyLkBxLffUX8HRcQzbI+2PGTSnpuQHk6NWn/Xv87pr -+LKABBr3zjOFgrX81p2QwEz3jDxNXzbOeZzhuvGXCX5GocuEO4n5EhDvXRDF4uht -uvVV5FsQv/sTOR0PNo1nELiAA8k3NYDxraB83q7wtsmErtECQQDYWMnq8mwRe49d -jIXNKJeNiuLUYxO3CLI/vx279gDKlKrt677trr1e7JZqm/DapEWG511tw3cW63gQ -+qxtgkw1AkEAxW0UeaNaJd7DApqwGAcS1JkygCKwzQ4ns/Co15qUgMkqCkmQU9AU -/zQpt2+BjdYVe50r/nr8K1KYwrBsyndrBwJBALe90N+FvFqswfoFmq2/R9eimTsg -WmIdNKYHPs2gBNQIp5MhoSpkOdkgvi8U+d33nkUQwryyQbZpjbN98mufOfECQEML -eBiW0NZrf+4yefqu7EYmgG/jWAdK91C0OaJ+bFAQAKbdtJXB5F+GZ2RUCbsRKNqB -1Z7mRRyxQA9dupRHWaECQQCM9bbCtfGesgvZlhBavlWavu8iCvJlAbGdf5QMlFQE -kABmZg84Fy3NUFCD+RXCuatb4Oo9P/WPIbjYiC4p0hLJ ------END RSA PRIVATE KEY----- + +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKbYgn2BYOQ9OVDf +s01QHTNrmYKxDxuL77x/ISrDvCXxk0GHeq1Nycv6b41l9CNQLQFeJzs9wwtWbgDc +gPYgBlAz5rF+r1oviG5Z6ubi5rq2923iBAqgvX7wkWZ0W8XDmlZb81ke2QimttV/ +sq1itTbtaYyFeu43TvVTOouzDTxzAgMBAAECgYAdDtw7K4tKdPdEhJFfx7IuQHEt +99RfwdFxDNsj7Y8ZNKem5AeTo1af9e/zumv4soAEGvfOM4WCtfzWnZDATPeMPE1f +Ns55nOG68ZcJfkahy4Q7ifkSEO9dEMXi6G269VXkWxC/+xM5HQ82jWcQuIADyTc1 +gPGtoHzervC2yYSu0QJBANhYyerybBF7j12Mhc0ol42K4tRjE7cIsj+/Hbv2AMqU +qu3rvu2uvV7slmqb8NqkRYbnXW3DdxbreBD6rG2CTDUCQQDFbRR5o1ol3sMCmrAY +BxLUmTKAIrDNDiez8KjXmpSAySoKSZBT0BT/NCm3b4GN1hV7nSv+evwrUpjCsGzK +d2sHAkEAt73Q34W8WqzB+gWarb9H16KZOyBaYh00pgc+zaAE1AinkyGhKmQ52SC+ +LxT53feeRRDCvLJBtmmNs33ya5858QJAQwt4GJbQ1mt/7jJ5+q7sRiaAb+NYB0r3 +ULQ5on5sUBAApt20lcHkX4ZnZFQJuxEo2oHVnuZFHLFAD126lEdZoQJBAIz1tsK1 +8Z6yC9mWEFq+VZq+7yIK8mUBsZ1/lAyUVASQAGZmDzgXLc1QUIP5FcK5q1vg6j0/ +9Y8huNiILinSEsk= +-----END PRIVATE KEY-----