2012-03-27 19 views

Respuesta

14

Usted puede hacer algo como esto:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 
kpg.initialize(2048); 

KeyPair kp = kpg.genKeyPair(); 

KeyFactory fact = KeyFactory.getInstance("RSA"); 

RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(), 
     RSAPublicKeySpec.class); 
saveToFile(PUBLIC_KEY_FILE, 
     pub.getModulus(), pub.getPublicExponent()); 

RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(), 
     RSAPrivateKeySpec.class); 
saveToFile(PRIVATE_KEY_FILE, 
     priv.getModulus(), priv.getPrivateExponent()); 

La función de ahorro:

private static void saveToFile(String fileName, 
           BigInteger mod, BigInteger exp) 
    throws SomeException { 
    ObjectOutputStream oout = new ObjectOutputStream(
      new BufferedOutputStream(new FileOutputStream(fileName))); 
    try { 
     oout.writeObject(mod); 
     oout.writeObject(exp); 
    } catch (Exception e) { 
     throw new SomeException(e); 
    } finally { 
     oout.close(); 
    } 
} 

Y leer el mismo camino de vuelta :

private static PublicKey readPublicKey() throws SomeException { 
    InputStream in = new FileInputStream(PUBLIC_KEY_FILE); 
    ObjectInputStream oin = 
      new ObjectInputStream(new BufferedInputStream(in)); 
    try { 
     BigInteger m = (BigInteger) oin.readObject(); 
     BigInteger e = (BigInteger) oin.readObject(); 
     RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e); 
     KeyFactory fact = KeyFactory.getInstance("RSA"); 
     PublicKey pubKey = fact.generatePublic(keySpec); 
     return pubKey; 
    } catch (Exception e) { 
     throw new SomeException(e); 
    } finally { 
     oin.close(); 
    } 
} 

lectura clave privada es similar.

+2

@segfault, También hay que tener en cuenta que es necesario '' para añadir este en 'AndroidManifest.xml ' – Israel

+6

¿Es seguro almacenar la clave privada en el almacenamiento a la que se puede acceder a través de otras aplicaciones? (Corrígeme si me equivoco, pero eso es lo que se hace aquí). – cph2117

+0

Depende de usted configurar los permisos en el archivo en el nivel del sistema operativo (por ejemplo, un usuario dedicado para la aplicación, etc.). Ovuosamente, está fuera del alcance de esta respuesta. –

0

http://snipplr.com/view/18368/

O

http://docs.oracle.com/javase/1.5.0/docs/api/java/security/KeyStore.html

O

http://java.sun.com/docs/books/tutorial/security/apisign/vstep2.html Esto es más prometedor

O

Es imposible asegurar una clave en un entorno no confiable. Puedes ofuscar tu código, puedes crear una clave a partir de variables arbitrarias, lo que sea. En última instancia, suponiendo que utiliza la biblioteca javax.crypto estándar, debe llamar a Mac.getInstance(), y en algún momento más tarde llamará a init() en esa instancia. Alguien que quiera tu llave lo obtendrá.

Sin embargo, creo que la solución es que ata la clave del entorno, no del programa. Una firma está destinada a decir que los datos se originaron a partir de una fuente conocida, y no se ha manipulado desde que la fuente lo proporcionó. Actualmente, intenta decir "garantizar que mi programa produjo los datos". En cambio, cambie su requisito de "garantizar que un usuario particular de mi programa haya producido los datos". La responsabilidad se transfiere a ese usuario para que cuide su clave.

7

Este bloque de código generará y almacenará un KeyPair en AndroidKeyStore. (NOTA: las capturas de excepción omitidos)

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); 
keyStore.load(null); 

String alias = "my_key"; // replace as required or get it as a function argument 

int nBefore = keyStore.size(); // debugging variable to help convince yourself this works 

// Create the keys if necessary 
if (!keyStore.containsAlias(alias)) { 

    Calendar notBefore = Calendar.getInstance(); 
    Calendar notAfter = Calendar.getInstance(); 
    notAfter.add(Calendar.YEAR, 1); 
    KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this) 
        .setAlias(alias) 
        .setKeyType("RSA") 
        .setKeySize(2048) 
        .setSubject(new X500Principal("CN=test")) 
        .setSerialNumber(BigInteger.ONE) 
        .setStartDate(notBefore.getTime()) 
        .setEndDate(notAfter.getTime()) 
        .build(); 
    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); 
    generator.initialize(spec); 

    KeyPair keyPair = generator.generateKeyPair(); 
} 
int nAfter = keyStore.size(); 
Log.v(TAG, "Before = " + nBefore + " After = " + nAfter); 

// Retrieve the keys 
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null); 
RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey(); 
RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey(); 

Log.v(TAG, "private key = " + privateKey.toString()); 
Log.v(TAG, "public key = " + publicKey.toString()); 
+0

OK, esto debería funcionar solo para Android. ¿Qué hay de Java? – Andy

+0

KeyPairGeneratorSpec ha quedado obsoleto. Por favor vea: https://stackoverflow.com/questions/35269954/keypairgeneratorspec-deprecated – Gary89

Cuestiones relacionadas