package hudson.plugins.ec2; import hudson.util.Secret; import org.apache.commons.codec.binary.Hex; import org.bouncycastle.openssl.PEMReader; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.security.DigestInputStream; import java.security.KeyPair; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Security; import com.xerox.amazonws.ec2.KeyPairInfo; import com.xerox.amazonws.ec2.Jec2; import com.xerox.amazonws.ec2.EC2Exception; /** * RSA private key (the one that you generate with ec2-add-keypair.) * * Starts with "----- BEGIN RSA PRIVATE KEY------\n". * * @author Kohsuke Kawaguchi */ final class EC2PrivateKey { private final Secret privateKey; EC2PrivateKey(String privateKey) { this.privateKey = Secret.fromString(privateKey.trim()); } /** * Obtains the fingerprint of the key in the "ab:cd:ef:...:12" format. */ /** * Obtains the fingerprint of the key in the "ab:cd:ef:...:12" format. */ public String getFingerprint() throws IOException { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); Reader r = new BufferedReader(new StringReader(privateKey.toString())); PEMReader pem = new PEMReader(r); KeyPair pair = (KeyPair) pem.readObject(); if(pair==null) return null; PrivateKey key = pair.getPrivate(); return digest(key); } /** * Is this file really a private key? */ public boolean isPrivateKey() throws IOException { BufferedReader br = new BufferedReader(new StringReader(privateKey.toString())); String line; while ((line = br.readLine()) != null) { if (line.equals("-----BEGIN RSA PRIVATE KEY-----")) return true; } return false; } /** * Finds the {@link KeyPairInfo} that corresponds to this key in EC2. */ public KeyPairInfo find(Jec2 ec2) throws IOException, EC2Exception { String fp = getFingerprint(); for(KeyPairInfo kp : ec2.describeKeyPairs(new String[0])) { if(kp.getKeyFingerprint().equalsIgnoreCase(fp)) return new KeyPairInfo(kp.getKeyName(),fp,privateKey.toString()); } return null; } @Override public int hashCode() { return privateKey.hashCode(); } @Override public boolean equals(Object that) { return that instanceof EC2PrivateKey && this.privateKey.equals(((EC2PrivateKey)that).privateKey); } @Override public String toString() { return privateKey.toString(); } /*package*/ static String digest(PrivateKey k) throws IOException { try { MessageDigest md5 = MessageDigest.getInstance("SHA1"); DigestInputStream in = new DigestInputStream(new ByteArrayInputStream(k.getEncoded()), md5); try { while (in.read(new byte[128]) > 0) ; // simply discard the input } finally { in.close(); } StringBuilder buf = new StringBuilder(); char[] hex = Hex.encodeHex(md5.digest()); for( int i=0; i<hex.length; i+=2 ) { if(buf.length()>0) buf.append(':'); buf.append(hex,i,2); } return buf.toString(); } catch (NoSuchAlgorithmException e) { throw new AssertionError(e); } } }