2014-01-15 5 views
5

Ich bin ziemlich vertraut mit PGP, und wie es funktioniert. Ich möchte einige Funktionen in ein Projekt einbeziehen, aber bisher hat meine Forschung mich in den Wahnsinn getrieben. Ich möchte einen öffentlichen Schlüssel mit einer definierten privaten Passphrase erstellen. Von dort aus würde ich den öffentlichen Schlüssel mit jemandem teilen, wo er dann eine Nachricht mit dem Schlüssel verschlüsseln und an mich zurückschicken kann, wo ich ihn entschlüsseln kann. Ich stelle mir vor, dass der Code ungefähr so ​​aussieht.Android integriert PGP in ein Projekt

Zu meinem privaten PGP-Schlüssel zu erzeugen:

PGPKey key = new PGPKey(); 
key.setPassPhrase("MySecretPassword!!!1"); 
key.generateRandomSharedKey(); 
key.build(); 

ich meinen Shared-Key an einen Freund gibt So verschlüsseln würde:

String encryptedText = PGPTools.Encrypt("Text to encrypt", getSharedKey()); 

den verschlüsselten String nach mir geschickt zu entschlüsseln ist zurück:

String decryptedText = PGPTools.Decrypt(encryptedText, key, "MySecretPassword!!!1") 

Offensichtlich weiß ich, dass ich auf eine Tonne von Details ausspringe. Durch meine Recherchen habe ich Referenzen zu Bibliotheken wie Bouncy Castle und Spongy Castle gesehen. Jede Hilfe würde sehr geschätzt werden!

+0

Sieht gut aus, was für Ärger hast du. –

+0

So schlimm es klingt, ich denke, ich suche mehr oder weniger nach genauem Code. Jedes Codebeispiel, das ich online finde, unterscheidet sich auf die eine oder andere Weise oder schließt wichtige Teile alle zusammen aus. –

+0

Willkommen in der Welt von OSS

Antwort

8

ich meine Lösung zu stellen, weil A. es extrem schwierig war, mach das funktionierend, und B. Wenn irgendwelche Krypto-Profis meinen Code auditieren wollen, wäre ich ewig dankbar.

I umfasste die vier folgenden Bibliotheken:

compile 'com.madgag.spongycastle:core:1.50.0.0' 
compile 'com.madgag.spongycastle:pg:1.50.0.0' 
compile 'com.madgag.spongycastle:pkix:1.50.0.0' 
compile 'com.madgag.spongycastle:prov:1.50.0.0' 

Hüpfburg muss als Sicherheitsanbieter hinzugefügt werden. Ich habe diesen Code in eine Klasse eingefügt, die einige andere Objekte beim Laden der App initialisiert.

static { 
    Security.addProvider(new BouncyCastleProvider()); 
} 

Hier ist die Utils-Klasse, die ich erstellt habe, die wirklich die Schrauben und Muttern enthält. leicht bearbeitet:

import com.example.Device; 

import org.spongycastle.bcpg.ArmoredInputStream; 
import org.spongycastle.bcpg.ArmoredOutputStream; 
import org.spongycastle.bcpg.HashAlgorithmTags; 
import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; 
import org.spongycastle.bcpg.sig.Features; 
import org.spongycastle.bcpg.sig.KeyFlags; 
import org.spongycastle.crypto.generators.RSAKeyPairGenerator; 
import org.spongycastle.crypto.params.RSAKeyGenerationParameters; 
import org.spongycastle.openpgp.PGPCompressedData; 
import org.spongycastle.openpgp.PGPCompressedDataGenerator; 
import org.spongycastle.openpgp.PGPEncryptedData; 
import org.spongycastle.openpgp.PGPEncryptedDataGenerator; 
import org.spongycastle.openpgp.PGPEncryptedDataList; 
import org.spongycastle.openpgp.PGPException; 
import org.spongycastle.openpgp.PGPKeyPair; 
import org.spongycastle.openpgp.PGPKeyRingGenerator; 
import org.spongycastle.openpgp.PGPLiteralData; 
import org.spongycastle.openpgp.PGPLiteralDataGenerator; 
import org.spongycastle.openpgp.PGPObjectFactory; 
import org.spongycastle.openpgp.PGPPrivateKey; 
import org.spongycastle.openpgp.PGPPublicKey; 
import org.spongycastle.openpgp.PGPPublicKeyEncryptedData; 
import org.spongycastle.openpgp.PGPPublicKeyRing; 
import org.spongycastle.openpgp.PGPSecretKey; 
import org.spongycastle.openpgp.PGPSecretKeyRing; 
import org.spongycastle.openpgp.PGPSignature; 
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator; 
import org.spongycastle.openpgp.PGPUtil; 
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; 
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor; 
import org.spongycastle.openpgp.operator.PGPDigestCalculator; 
import org.spongycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder; 
import org.spongycastle.openpgp.operator.bc.BcPBESecretKeyEncryptorBuilder; 
import org.spongycastle.openpgp.operator.bc.BcPGPContentSignerBuilder; 
import org.spongycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider; 
import org.spongycastle.openpgp.operator.bc.BcPGPKeyPair; 
import org.spongycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory; 
import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder; 
import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator; 

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.math.BigInteger; 
import java.nio.charset.Charset; 
import java.security.SecureRandom; 
import java.util.Date; 
import java.util.Iterator; 

public class PgpUtils { 
    private static final String PROVIDER = "SC"; 
    private static final String KEY_RING_ID = "[email protected]"; 

    public static String decrypt(String encryptedText, String password) throws Exception { 
     byte[] encrypted = encryptedText.getBytes(); 
     InputStream in = new ByteArrayInputStream(encrypted); 
     in = PGPUtil.getDecoderStream(in); 
     PGPObjectFactory pgpF = new PGPObjectFactory(in); 
     PGPEncryptedDataList enc; 
     Object o = pgpF.nextObject(); 
     if (o instanceof PGPEncryptedDataList) { 
      enc = (PGPEncryptedDataList) o; 
     } else { 
      enc = (PGPEncryptedDataList) pgpF.nextObject(); 
     } 
     PGPPrivateKey sKey = null; 
     PGPPublicKeyEncryptedData pbe = null; 
     while (sKey == null && enc.getEncryptedDataObjects().hasNext()) { 
      pbe = (PGPPublicKeyEncryptedData)enc.getEncryptedDataObjects().next(); 
      sKey = getPrivateKey(getPGPSecretKeyRing(), pbe.getKeyID(), password.toCharArray()); 
     } 
     if (pbe != null) { 
      InputStream clear = pbe.getDataStream(new BcPublicKeyDataDecryptorFactory(sKey)); 
      PGPObjectFactory pgpFact = new PGPObjectFactory(clear); 
      PGPCompressedData cData = (PGPCompressedData) pgpFact.nextObject(); 
      pgpFact = new PGPObjectFactory(cData.getDataStream()); 
      PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject(); 
      InputStream unc = ld.getInputStream(); 
      ByteArrayOutputStream out = new ByteArrayOutputStream(); 
      int ch; 
      while ((ch = unc.read()) >= 0) { 
       out.write(ch); 
      } 
      byte[] returnBytes = out.toByteArray(); 
      out.close(); 
      return new String(returnBytes); 
     } 
     return null; 
    } 

    private static PGPPublicKey getPublicKey(PGPPublicKeyRing publicKeyRing) { 
     Iterator<?> kIt = publicKeyRing.getPublicKeys(); 
     while (kIt.hasNext()) { 
      PGPPublicKey k = (PGPPublicKey) kIt.next(); 
      if (k.isEncryptionKey()) { 
       return k; 
      } 
     } 
     return null; 
    } 

    private static PGPPrivateKey getPrivateKey(PGPSecretKeyRing keyRing, long keyID, char[] pass) throws PGPException { 
     PGPSecretKey secretKey = keyRing.getSecretKey(keyID); 
     PBESecretKeyDecryptor decryptor = new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass); 
     return secretKey.extractPrivateKey(decryptor); 
    } 

    public static String encrypt(String msgText) throws IOException, PGPException { 
     byte[] clearData = msgText.getBytes(); 
     PGPPublicKey encKey = getPublicKey(getPGPPublicKeyRing()); 
     ByteArrayOutputStream encOut = new ByteArrayOutputStream(); 
     OutputStream out = new ArmoredOutputStream(encOut); 
     ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 
     PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedDataGenerator.ZIP); 
     OutputStream cos = comData.open(bOut); 
     PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator(); 
     OutputStream pOut = lData.open(cos, PGPLiteralData.BINARY, PGPLiteralData.CONSOLE, clearData.length, new Date()); 
     pOut.write(clearData); 
     lData.close(); 
     comData.close(); 
     PGPEncryptedDataGenerator encGen = 
       new PGPEncryptedDataGenerator(
         new JcePGPDataEncryptorBuilder(PGPEncryptedData.AES_256).setWithIntegrityPacket(true).setSecureRandom(
           new SecureRandom()).setProvider(PROVIDER)); 
     if (encKey != null) { 
      encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider(PROVIDER)); 
      byte[] bytes = bOut.toByteArray(); 
      OutputStream cOut = encGen.open(out, bytes.length); 
      cOut.write(bytes); 
      cOut.close(); 
     } 
     out.close(); 
     return new String(encOut.toByteArray()); 
    } 

    public final static PGPKeyRingGenerator generateKeyRingGenerator (char[] pass) throws PGPException{ 
     RSAKeyPairGenerator kpg = new RSAKeyPairGenerator(); 
     kpg.init(new RSAKeyGenerationParameters(BigInteger.valueOf(0x10001), new SecureRandom(), 2048, 12)); 
     PGPKeyPair rsakp_sign = new BcPGPKeyPair(PGPPublicKey.RSA_SIGN, kpg.generateKeyPair(), new Date()); 
     PGPKeyPair rsakp_enc = new BcPGPKeyPair(PGPPublicKey.RSA_ENCRYPT, kpg.generateKeyPair(), new Date()); 
     PGPSignatureSubpacketGenerator signhashgen = new PGPSignatureSubpacketGenerator(); 
     signhashgen.setKeyFlags(false, KeyFlags.SIGN_DATA|KeyFlags.CERTIFY_OTHER|KeyFlags.SHARED); 
     signhashgen.setPreferredSymmetricAlgorithms(false, new int[]{SymmetricKeyAlgorithmTags.AES_256, SymmetricKeyAlgorithmTags.AES_192, SymmetricKeyAlgorithmTags.AES_128}); 
     signhashgen.setPreferredHashAlgorithms(false, new int[]{HashAlgorithmTags.SHA256, HashAlgorithmTags.SHA1, HashAlgorithmTags.SHA384, HashAlgorithmTags.SHA512, HashAlgorithmTags.SHA224}); 
     signhashgen.setFeature(false, Features.FEATURE_MODIFICATION_DETECTION); 
     PGPSignatureSubpacketGenerator enchashgen = new PGPSignatureSubpacketGenerator(); 
     enchashgen.setKeyFlags(false, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE); 
     PGPDigestCalculator sha1Calc = new BcPGPDigestCalculatorProvider().get(HashAlgorithmTags.SHA1); 
     PGPDigestCalculator sha256Calc = new BcPGPDigestCalculatorProvider().get(HashAlgorithmTags.SHA256); 
     PBESecretKeyEncryptor pske = (new BcPBESecretKeyEncryptorBuilder(PGPEncryptedData.AES_256, sha256Calc, 0xc0)).build(pass); 
     PGPKeyRingGenerator keyRingGen = new PGPKeyRingGenerator (PGPSignature.POSITIVE_CERTIFICATION, rsakp_sign, 
       KEY_RING_ID, sha1Calc, signhashgen.generate(), null, new BcPGPContentSignerBuilder(rsakp_sign.getPublicKey().getAlgorithm(), 
       HashAlgorithmTags.SHA1), pske); 
     keyRingGen.addSubKey(rsakp_enc, enchashgen.generate(), null); 
     return keyRingGen; 
    } 

    private static PGPPublicKeyRing getPGPPublicKeyRing() throws IOException { 
     ArmoredInputStream ais = new ArmoredInputStream(new ByteArrayInputStream(Device.getDevice().getPgpPublicKey().getBytes())); 
     return (PGPPublicKeyRing) new PGPObjectFactory(ais).nextObject(); 
    } 

    private static PGPSecretKeyRing getPGPSecretKeyRing() throws IOException { 
     ArmoredInputStream ais = new ArmoredInputStream(new ByteArrayInputStream(Device.getDevice().getPgpSecretKey().getBytes())); 
     return (PGPSecretKeyRing) new PGPObjectFactory(ais).nextObject(); 
    } 

    public final static String genPGPPublicKey (PGPKeyRingGenerator krgen) throws IOException { 
     ByteArrayOutputStream baosPkr = new ByteArrayOutputStream(); 
     PGPPublicKeyRing pkr = krgen.generatePublicKeyRing(); 
     ArmoredOutputStream armoredStreamPkr = new ArmoredOutputStream(baosPkr); 
     pkr.encode(armoredStreamPkr); 
     armoredStreamPkr.close(); 
     return new String(baosPkr.toByteArray(), Charset.defaultCharset()); 
    } 

    public final static String genPGPPrivKey (PGPKeyRingGenerator krgen) throws IOException { 
     ByteArrayOutputStream baosPriv = new ByteArrayOutputStream(); 
     PGPSecretKeyRing skr = krgen.generateSecretKeyRing(); 
     ArmoredOutputStream armoredStreamPriv = new ArmoredOutputStream(baosPriv); 
     skr.encode(armoredStreamPriv); 
     armoredStreamPriv.close(); 
     return new String(baosPriv.toByteArray(), Charset.defaultCharset()); 
    } 
} 

Hier ist, wie ich die privaten und öffentlichen Schlüssel erstellen:

final PGPKeyRingGenerator krgen = PgpUtils.generateKeyRingGenerator("password".toCharArray()); 
String pgpPublicKey = PgpUtils.genPGPPublicKey(krgen); 
String pgpSecretKey = PgpUtils.genPGPPrivKey(krgen); 

Und schließlich Verschlüsseln und Entschlüsseln von Ihren eigenen öffentlichen Schlüssel:

String encrypted = PgpUtils.encrypt("message text"); 
String decrypted = PgpUtils.decrypt(encrypted, "Password"); 
+0

Großartige Arbeit Joe. Es funktioniert perfekt für mich. Du hast meine Zeit gerettet .... – Hareesh

+0

Danke, es hat funktioniert. Ich musste nur geringfügige Änderungen für die Dekodierung vornehmen, da die verschlüsselte Nachricht nicht am Serverende komprimiert wird. – Fenil

+0

Irgendeine Idee, wie man für iOS, das Open Source ist, ähnlich zu implementieren? – Fenil

1

Sieht aus, als ob Sie ein öffentliches Schlüsselpaar mit BouncyCastle generieren möchten?

Dieser fragt, wie es ohne Passwort zu tun, aber Sie können einen Blick darauf werfen, wie es mit einem Passwort zu tun zu: How to generate OpenPGP KeyPair without passphrase using BouncyCastle?

+1

Ja, das ist sehr nah. Code-Beispiele zu finden, wie man das Passwort definiert, war für mich nahezu unmöglich. –

+0

@JoeGoble Ich bin froh, Ihnen helfen zu können! – Dannie

+0

BC ist massive Bibliothek und Integration in Ihre App sollte ein letzter Ausweg sein. –