Java - пример асимметричной криптографии
Асимметричная криптография, также известная какPublic Key Cryptography
, - это система шифрования, в которой используются два разных, но однозначно связанных криптографических ключа. Данные, зашифрованные одним ключом, можно расшифровать другим. Эти ключи известны как пара открытого и закрытого ключей, и, как следует из названия, закрытый ключ должен оставаться закрытым, в то время как открытый ключ может быть распространен. Самыми популярными алгоритмами открытого ключа являются RSA, Diffie-Hellman, ElGamal, DSS.
1. Создание пары открытого и закрытого ключей
Существует несколько способов создания пары «открытый-закрытый ключ» в зависимости от вашей платформы. В этом примере мы создадим пару с помощью Java. Криптографический алгоритм, который мы будем использовать в этом примере, - это RSA.
GenerateKeys.java
package com.techfou.keypair; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; public class GenerateKeys { private KeyPairGenerator keyGen; private KeyPair pair; private PrivateKey privateKey; private PublicKey publicKey; public GenerateKeys(int keylength) throws NoSuchAlgorithmException, NoSuchProviderException { this.keyGen = KeyPairGenerator.getInstance("RSA"); this.keyGen.initialize(keylength); } public void createKeys() { this.pair = this.keyGen.generateKeyPair(); this.privateKey = pair.getPrivate(); this.publicKey = pair.getPublic(); } public PrivateKey getPrivateKey() { return this.privateKey; } public PublicKey getPublicKey() { return this.publicKey; } public void writeToFile(String path, byte[] key) throws IOException { File f = new File(path); f.getParentFile().mkdirs(); FileOutputStream fos = new FileOutputStream(f); fos.write(key); fos.flush(); fos.close(); } public static void main(String[] args) { GenerateKeys gk; try { gk = new GenerateKeys(1024); gk.createKeys(); gk.writeToFile("KeyPair/publicKey", gk.getPublicKey().getEncoded()); gk.writeToFile("KeyPair/privateKey", gk.getPrivateKey().getEncoded()); } catch (NoSuchAlgorithmException | NoSuchProviderException e) { System.err.println(e.getMessage()); } catch (IOException e) { System.err.println(e.getMessage()); } } }
Выход:
2. Создайте текстовый файл для шифрования
3. Используйте пару ключей для шифрования и дешифрования данных
В этом примере мы создаем класс, который может загружать открытый и закрытый ключи из своих файлов, а затем использует их для шифрования и дешифрованияString
иFile
. Чтобы запустить этот пример, вам необходимо запустить приведенный выше код для генерации ключей или загрузить исходный код ниже.
Note
Вам нужно получитьApache
Commons Codec и добавить его в свою программу.
AsymmetricCryptography.java
package com.techfou.asymmetric; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.file.Files; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import org.apache.commons.codec.binary.Base64; public class AsymmetricCryptography { private Cipher cipher; public AsymmetricCryptography() throws NoSuchAlgorithmException, NoSuchPaddingException { this.cipher = Cipher.getInstance("RSA"); } // https://docs.oracle.com/javase/8/docs/api/java/security/spec/PKCS8EncodedKeySpec.html public PrivateKey getPrivate(String filename) throws Exception { byte[] keyBytes = Files.readAllBytes(new File(filename).toPath()); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate(spec); } // https://docs.oracle.com/javase/8/docs/api/java/security/spec/X509EncodedKeySpec.html public PublicKey getPublic(String filename) throws Exception { byte[] keyBytes = Files.readAllBytes(new File(filename).toPath()); X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePublic(spec); } public void encryptFile(byte[] input, File output, PrivateKey key) throws IOException, GeneralSecurityException { this.cipher.init(Cipher.ENCRYPT_MODE, key); writeToFile(output, this.cipher.doFinal(input)); } public void decryptFile(byte[] input, File output, PublicKey key) throws IOException, GeneralSecurityException { this.cipher.init(Cipher.DECRYPT_MODE, key); writeToFile(output, this.cipher.doFinal(input)); } private void writeToFile(File output, byte[] toWrite) throws IllegalBlockSizeException, BadPaddingException, IOException { FileOutputStream fos = new FileOutputStream(output); fos.write(toWrite); fos.flush(); fos.close(); } public String encryptText(String msg, PrivateKey key) throws NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException { this.cipher.init(Cipher.ENCRYPT_MODE, key); return Base64.encodeBase64String(cipher.doFinal(msg.getBytes("UTF-8"))); } public String decryptText(String msg, PublicKey key) throws InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException { this.cipher.init(Cipher.DECRYPT_MODE, key); return new String(cipher.doFinal(Base64.decodeBase64(msg)), "UTF-8"); } public byte[] getFileInBytes(File f) throws IOException { FileInputStream fis = new FileInputStream(f); byte[] fbytes = new byte[(int) f.length()]; fis.read(fbytes); fis.close(); return fbytes; } public static void main(String[] args) throws Exception { AsymmetricCryptography ac = new AsymmetricCryptography(); PrivateKey privateKey = ac.getPrivate("KeyPair/privateKey"); PublicKey publicKey = ac.getPublic("KeyPair/publicKey"); String msg = "Cryptography is fun!"; String encrypted_msg = ac.encryptText(msg, privateKey); String decrypted_msg = ac.decryptText(encrypted_msg, publicKey); System.out.println("Original Message: " + msg + "\nEncrypted Message: " + encrypted_msg + "\nDecrypted Message: " + decrypted_msg); if (new File("KeyPair/text.txt").exists()) { ac.encryptFile(ac.getFileInBytes(new File("KeyPair/text.txt")), new File("KeyPair/text_encrypted.txt"),privateKey); ac.decryptFile(ac.getFileInBytes(new File("KeyPair/text_encrypted.txt")), new File("KeyPair/text_decrypted.txt"), publicKey); } else { System.out.println("Create a file text.txt under folder KeyPair"); } } }
Выход:
Original Message: Cryptography is fun! Encrypted Message: NZY+9v4AWoADVBQiFmS8ake6dG8M9v4WDf4TSPKgGPoKeJtHxEWVFGFL57qR2mbuknn8WYjfjcN+BA/ RDsDQ9Q5SxQFLi8GE7A/6fdURjO+Vz3qYFaefpXccp7SnObKXnFfUNp00m5BtMSdTLEYfngF9UDBVYVFz0EZwuyP50xY= Decrypted Message: Cryptography is fun!
Зашифрованный текст:
Расшифрованный текст: