Created
January 20, 2016 20:57
-
-
Save rbrick/f8484965bf774df7b9a5 to your computer and use it in GitHub Desktop.
Simple Java implementation of PGP (Pretty Good Privacy)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javax.crypto.Cipher; | |
import java.nio.ByteBuffer; | |
import java.security.GeneralSecurityException; | |
import java.security.KeyFactory; | |
import java.security.KeyPair; | |
import java.security.KeyPairGenerator; | |
import java.security.NoSuchAlgorithmException; | |
import java.security.PrivateKey; | |
import java.security.PublicKey; | |
import java.security.SecureRandom; | |
import java.security.spec.InvalidKeySpecException; | |
import java.security.spec.X509EncodedKeySpec; | |
/** | |
* An implementation of PGP encryption (PGP = Pretty Good Privacy) | |
*/ | |
public final class JavaPGP { | |
/** | |
* The message is created like so: | |
* - Generates a random KeyPair | |
* - Encrypt the message with the private key from the generated key pair | |
* - Encrypt the generated public key with given public key | |
* | |
* @param message The message to encrypt | |
* @param key The key to encrypt with | |
* @return The encrypted message | |
* @throws GeneralSecurityException | |
*/ | |
public static byte[] encrypt(byte[] message, PublicKey key) throws GeneralSecurityException { | |
KeyPair pair = generateKeyPair(); | |
PrivateKey privateKey = pair.getPrivate(); | |
Cipher cipher = Cipher.getInstance("RSA"); | |
cipher.init(Cipher.ENCRYPT_MODE, privateKey); | |
byte[] encryptedMessage = cipher.doFinal(message); | |
cipher.init(Cipher.ENCRYPT_MODE, key); | |
byte[] encryptedPublicKey = cipher.doFinal(pair.getPublic().getEncoded()); | |
ByteBuffer buffer = ByteBuffer.allocate((encryptedPublicKey.length + encryptedMessage.length) + 4); | |
buffer.putInt(encryptedPublicKey.length); | |
buffer.put(encryptedPublicKey); | |
buffer.put(encryptedMessage); | |
return buffer.array(); | |
} | |
/** | |
* The message is decrypted like so: | |
* - Read the encrypted public key | |
* - Decrypt the public key with the private key | |
* - Read the encrypted message | |
* - Use the decrypted public key to decrypt the encrypted message | |
* | |
* @param message The encrypted message | |
* @param key The private key | |
* @return The decrypted message | |
* @throws GeneralSecurityException | |
*/ | |
public static byte[] decrypt(byte[] message, PrivateKey key) throws GeneralSecurityException { | |
ByteBuffer buffer = ByteBuffer.wrap(message); | |
int keyLength = buffer.getInt(); | |
byte[] encyptedPublicKey = new byte[keyLength]; | |
buffer.get(encyptedPublicKey); | |
Cipher cipher = Cipher.getInstance("RSA"); | |
cipher.init(Cipher.DECRYPT_MODE, key); | |
byte[] encodedPublicKey = cipher.doFinal(encyptedPublicKey); | |
PublicKey publicKey = getPublicKey(encodedPublicKey); | |
cipher.init(Cipher.DECRYPT_MODE, publicKey); | |
byte[] encryptedMessage = new byte[buffer.remaining()]; | |
buffer.get(encryptedMessage); | |
return cipher.doFinal(encryptedMessage); | |
} | |
protected static PublicKey getPublicKey(byte[] encodedKey) throws NoSuchAlgorithmException, InvalidKeySpecException { | |
KeyFactory factory = KeyFactory.getInstance("RSA"); | |
X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(encodedKey); | |
return factory.generatePublic(encodedKeySpec); | |
} | |
protected static KeyPair generateKeyPair() throws NoSuchAlgorithmException { | |
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); | |
keyPairGenerator.initialize(1024, SecureRandom.getInstance("SHA1PRNG")); | |
return keyPairGenerator.generateKeyPair(); | |
} | |
} |
@rbrick Could you add a note to clarify that this code is about encryption and decryption in general (and not PGP in particular) ?
Since, PGP defines its own cipher mode, you are likely to need an implementation such as Bouncy Castle for this to work correctly
https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java#L10
i.e. following may not produce what PGP expects.
Cipher cipher = Cipher.getInstance("RSA");
Useful.
This isn't pgp
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It good code, but how to get Private Key from encoded key? I tried to do it like here, but it is'nt working.