package com.eucalyptus.keys;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.List;
import org.apache.log4j.Logger;
import org.bouncycastle.util.encoders.Base64;
import com.eucalyptus.auth.crypto.Certs;
import com.eucalyptus.entities.EntityWrapper;
import com.eucalyptus.entities.SshKeyPair;
import com.eucalyptus.util.EucalyptusCloudException;
import com.google.common.collect.Lists;
public class KeyPairUtil {
private static Logger LOG = Logger.getLogger( KeyPairUtil.class );
public static EntityWrapper<SshKeyPair> getEntityWrapper( ) {
EntityWrapper<SshKeyPair> db = new EntityWrapper<SshKeyPair>( );
return db;
}
public static List<SshKeyPair> getUserKeyPairs( String userName ) {
EntityWrapper<SshKeyPair> db = KeyPairUtil.getEntityWrapper( );
List<SshKeyPair> keys = Lists.newArrayList( );
try {
keys = db.query( new SshKeyPair( userName ) );
db.commit( );
} catch ( Throwable e ) {
db.rollback( );
}
return keys;
}
public static SshKeyPair getUserKeyPair( String userName, String keyName ) throws EucalyptusCloudException {
EntityWrapper<SshKeyPair> db = KeyPairUtil.getEntityWrapper( );
SshKeyPair key = null;
try {
key = db.getUnique( new SshKeyPair( userName, keyName ) );
db.commit( );
} catch ( Throwable e ) {
db.rollback( );
throw new EucalyptusCloudException( "Failed to find key pair: " + keyName + " for user " + userName, e );
}
return key;
}
public static SshKeyPair getUserKeyPairByValue( String userName, String keyValue ) throws EucalyptusCloudException {
EntityWrapper<SshKeyPair> db = KeyPairUtil.getEntityWrapper( );
SshKeyPair key = null;
try {
SshKeyPair searchKey = new SshKeyPair( userName );
searchKey.setPublicKey( keyValue );
key = db.getUnique( searchKey );
db.commit( );
} catch ( Throwable e ) {
db.rollback( );
throw new EucalyptusCloudException( "Failed to find key pair associated with public key " + keyValue, e );
}
return key;
}
public static SshKeyPair deleteUserKeyPair( String userName, String keyName ) throws EucalyptusCloudException {
EntityWrapper<SshKeyPair> db = KeyPairUtil.getEntityWrapper( );
SshKeyPair key = null;
try {
key = db.getUnique( new SshKeyPair( userName, keyName ) );
db.delete( key );
db.commit( );
} catch ( Throwable e ) {
db.rollback( );
throw new EucalyptusCloudException( "Failed to find key pair: " + keyName, e );
}
return key;
}
public static PrivateKey createUserKeyPair( String userName, String keyName ) throws EucalyptusCloudException {
SshKeyPair newKey = new SshKeyPair( userName, keyName );
KeyPair newKeys = null;
try {
newKeys = Certs.generateKeyPair( );
String authKeyString = getAuthKeyString( userName, newKeys );
newKey.setPublicKey( authKeyString );
newKey.setFingerPrint( Certs.getFingerPrint( newKeys.getPrivate( ) ) );
} catch ( Exception e ) {
throw new EucalyptusCloudException( "KeyPair generation error: Key pair creation failed.", e );
}
EntityWrapper<SshKeyPair> db = KeyPairUtil.getEntityWrapper( );
try {
db.add( newKey );
db.commit( );
} catch ( Throwable e1 ) {
db.rollback( );
throw new EucalyptusCloudException( "KeyPair generation error. Key pair: " + keyName + " already exists." );
}
return newKeys.getPrivate( );
}
private static String getAuthKeyString( String userName, KeyPair newKeys ) {
RSAPublicKey publicKey = ( RSAPublicKey ) newKeys.getPublic( );
byte[] keyType = "ssh-rsa".getBytes( );
byte[] expBlob = publicKey.getPublicExponent( ).toByteArray( );
byte[] modBlob = publicKey.getModulus( ).toByteArray( );
byte[] authKeyBlob = new byte[3 * 4 + keyType.length + expBlob.length + modBlob.length];
byte[] lenArray = null;
lenArray = BigInteger.valueOf( keyType.length ).toByteArray( );
System.arraycopy( lenArray, 0, authKeyBlob, 4 - lenArray.length, lenArray.length );
System.arraycopy( keyType, 0, authKeyBlob, 4, keyType.length );
lenArray = BigInteger.valueOf( expBlob.length ).toByteArray( );
System.arraycopy( lenArray, 0, authKeyBlob, 4 + keyType.length + 4 - lenArray.length, lenArray.length );
System.arraycopy( expBlob, 0, authKeyBlob, 4 + ( 4 + keyType.length ), expBlob.length );
lenArray = BigInteger.valueOf( modBlob.length ).toByteArray( );
System.arraycopy( lenArray, 0, authKeyBlob, 4 + expBlob.length + 4 + keyType.length + 4 - lenArray.length, lenArray.length );
System.arraycopy( modBlob, 0, authKeyBlob, 4 + ( 4 + expBlob.length + ( 4 + keyType.length ) ), modBlob.length );
String authKeyString = String.format( "%s %s %s@eucalyptus", new String( keyType ), new String( Base64.encode( authKeyBlob ) ), userName );
return authKeyString;
}
}