1.1.46. fejezet, Titkosítás, hitelesítés
Beküldte pzoli - 2022, szeptember 14 - 11:25de
Aszimmetrukus (RSA) és szimmetrikus (AES) titkosításra és hitelesítésre mintaprogram. A Windows-MY Keystore és JKS kezelésére ajánlom a KeyStore Explorer-t
package hu.infokristaly.homework4signencdec; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.nio.charset.Charset; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Security; import java.security.Signature; import java.security.cert.Certificate; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import sun.security.mscapi.SunMSCAPI; public class Homework4SignEncDec { private static final String fileName = "c:\\temp\\app-icon.png"; private static final String ASSIMETRIC_ALGORITHM = "RSA"; private static final String ASSIMETRIC_CHIPER_TRANSFORMATION = "RSA/ECB/PKCS1Padding"; static final int ASSIMETRIC_ALGORITHM_KEYSIZE = 1024; private static final String SIMETRIC_ALGORITHM = "AES"; private static final String SIMETRIC_CHIPER_ALGORITHM = "AES/CTR/NoPadding"; private static final int SIMETRIC_ALGORITHM_KEYSIZE = 256; static final String SIGNATURE_ALGORITHM = "SHA1withRSA"; static final String MESSAGE = "Árvíztűrő tükörfúró gép"; private static final String SIMETRIC_ALGORITHM_PASSWORD = "Secret"; private static final String ALIAS = "pzoli"; private static final String WINDOWSMY_KEYSTORE_PASSWORD = ""; private static final String WINDOWSMY_CERT_PASSWORD = ""; private static final String JKS_FILE = "c:\\temp\\mykeystore.jks"; private static final String JKS_KEYSTORE_PASSWORD = "pWd13X"; private static final String JKS_CERT_PASSWORD = "xTr24P"; private static final String RSA_ENC_SUFFIX = ".rsa.enc"; private static final String RSA_DEC_SUFFIX = ".rsa.dec"; private static final String AES_ENC_SUFFIX = ".aes.enc"; private static final String AES_DEC_SUFFIX = ".aes.dec"; private static KeyStore keyStore; public static void main(String[] args) throws Exception { Security.setProperty("crypto.policy", "unlimited"); testSign(); testAES(); testWindowsMyKeystore(); testJKSKeyStore(); } private static void testSign() throws Exception { keyStore = KeyStore.getInstance("Windows-MY", new SunMSCAPI()); keyStore.load(null, WINDOWSMY_KEYSTORE_PASSWORD.toCharArray()); String signatureText = signDocument(MESSAGE); verifySignature(MESSAGE, signatureText); } private static void testAES() throws Exception { int maxKeySize = javax.crypto.Cipher.getMaxAllowedKeyLength(SIMETRIC_ALGORITHM); System.out.println("Max key size: " + maxKeySize); IvParameterSpec generatedIv = getIVSecureRandom(SIMETRIC_ALGORITHM); SecretKey key = getPasswordBasedKey(SIMETRIC_ALGORITHM, SIMETRIC_ALGORITHM_KEYSIZE, SIMETRIC_ALGORITHM_PASSWORD.toCharArray()); // Initialization vector to store String plainIvBase64 = new String(Base64.getEncoder().encode(generatedIv.getIV())); byte[] encryptedText = aesEncryptMessage(MESSAGE, generatedIv, key); // restored Initialization vector byte[] restoredIvBytes = Base64.getDecoder().decode(plainIvBase64); IvParameterSpec restoredIv = new IvParameterSpec(restoredIvBytes); aesDecryptMessage(encryptedText, restoredIv, key); aesEncryptFile(restoredIv, key); aesDecryptFile(encryptedText, restoredIv, key); } private static void testWindowsMyKeystore() throws Exception { keyStore = KeyStore.getInstance("Windows-MY", new SunMSCAPI()); keyStore.load(null, WINDOWSMY_KEYSTORE_PASSWORD.toCharArray()); rsaEncryptFile(fileName, fileName + RSA_ENC_SUFFIX); rsaDecryptFile(fileName + RSA_ENC_SUFFIX, fileName + RSA_DEC_SUFFIX, WINDOWSMY_CERT_PASSWORD); } private static void testJKSKeyStore() throws Exception { keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); InputStream in = new FileInputStream(JKS_FILE); keyStore.load(in, JKS_KEYSTORE_PASSWORD.toCharArray()); rsaEncryptFile(fileName, fileName + ".jks" + RSA_ENC_SUFFIX); rsaDecryptFile(fileName + ".jks" + RSA_ENC_SUFFIX, fileName + ".jks" + RSA_DEC_SUFFIX, JKS_CERT_PASSWORD); } private static byte[] aesEncryptMessage(String message, IvParameterSpec iv, SecretKey key) throws Exception { Cipher encCipher = Cipher.getInstance(SIMETRIC_CHIPER_ALGORITHM); encCipher.init(Cipher.ENCRYPT_MODE, key, iv); byte[] encryptedText = encCipher.doFinal(MESSAGE.getBytes("UTF8")); return encryptedText; } private static void aesDecryptMessage(byte[] encryptedText, IvParameterSpec iv, SecretKey key) throws Exception { Cipher decCipher = Cipher.getInstance(SIMETRIC_CHIPER_ALGORITHM); decCipher.init(Cipher.DECRYPT_MODE, key, iv); byte[] decryptedText = decCipher.doFinal(encryptedText); String result = new String(decryptedText, Charset.forName("UTF8")); System.out.println("[" + result + "]"); } private static void aesEncryptFile(IvParameterSpec iv, SecretKey key) throws Exception { Cipher encCipher = Cipher.getInstance(SIMETRIC_CHIPER_ALGORITHM); encCipher.init(Cipher.ENCRYPT_MODE, key, iv); byte[] buf = new byte[1024]; int bufl; try (FileOutputStream outputWriter = new FileOutputStream(fileName + AES_ENC_SUFFIX); FileInputStream inputReader = new FileInputStream(fileName);) { byte[] cipherText = null; while ((bufl = inputReader.read(buf)) != -1) { cipherText = encCipher.doFinal(copyBytes(buf, bufl)); outputWriter.write(cipherText); } outputWriter.flush(); } } private static void aesDecryptFile(byte[] encryptedText, IvParameterSpec iv, SecretKey key) throws Exception { Cipher decCipher = Cipher.getInstance(SIMETRIC_CHIPER_ALGORITHM); decCipher.init(Cipher.DECRYPT_MODE, key, iv); byte[] outBuf = new byte[1024]; int bufl; try (FileOutputStream outputWriter = new FileOutputStream(fileName + AES_DEC_SUFFIX); FileInputStream inputReader = new FileInputStream(fileName + AES_ENC_SUFFIX);) { byte[] plainBytes = null; while ((bufl = inputReader.read(outBuf)) != -1) { plainBytes = decCipher.doFinal(copyBytes(outBuf, bufl)); outputWriter.write(plainBytes); } outputWriter.flush(); } } private static void rsaEncryptFile(String inFileName, String outFileName) throws Exception { Certificate cert = keyStore.getCertificate(ALIAS); PublicKey pubKey = cert.getPublicKey(); Cipher encryptCipher = Cipher.getInstance(ASSIMETRIC_CHIPER_TRANSFORMATION); encryptCipher.init(Cipher.ENCRYPT_MODE, pubKey); byte[] buf = new byte[100]; int bufl; try (FileOutputStream outputWriter = new FileOutputStream(outFileName); FileInputStream inputReader = new FileInputStream(inFileName);) { byte[] cipherText = null; while ((bufl = inputReader.read(buf)) != -1) { cipherText = encryptCipher.doFinal(copyBytes(buf, bufl)); outputWriter.write(cipherText); } outputWriter.flush(); } } private static void rsaDecryptFile(String inFileName, String outFileName, String alias_password) throws Exception { KeyStore.PasswordProtection keyPassword = new KeyStore.PasswordProtection(alias_password.toCharArray()); KeyStore.PrivateKeyEntry selectedKey = (KeyStore.PrivateKeyEntry) keyStore.getEntry(ALIAS, keyPassword); PrivateKey privKey = selectedKey.getPrivateKey(); Cipher decryptCipher = Cipher.getInstance(ASSIMETRIC_CHIPER_TRANSFORMATION); decryptCipher.init(Cipher.DECRYPT_MODE, privKey); int outputSize = decryptCipher.getOutputSize(0); byte[] buf = new byte[outputSize]; int bufl; try (FileOutputStream outputWriter = new FileOutputStream(outFileName); FileInputStream inputReader = new FileInputStream(inFileName);) { byte[] decryptedText = null; while ((bufl = inputReader.read(buf)) != -1) { decryptedText = decryptCipher.doFinal(copyBytes(buf, bufl)); outputWriter.write(decryptedText); } outputWriter.flush(); } } public static boolean verifySignature(String text, String signatureText) throws Exception { boolean result = false; PublicKey publicKey = (PublicKey) keyStore.getCertificate(ALIAS).getPublicKey(); try { Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); byte[] signatureBytes = Base64.getDecoder().decode(signatureText); signature.initVerify(publicKey); signature.update(text.getBytes()); result = signature.verify(signatureBytes); System.out.println("signature verified: " + result); } catch (Exception ex) { ex.printStackTrace(); } return result; } private static String signDocument(final String messageToSign) throws Exception { KeyStore.PasswordProtection keyPassword = new KeyStore.PasswordProtection(WINDOWSMY_CERT_PASSWORD.toCharArray()); KeyStore.PrivateKeyEntry selectedKey = (KeyStore.PrivateKeyEntry) keyStore.getEntry(ALIAS, keyPassword); PrivateKey privKey = selectedKey.getPrivateKey(); Signature dmSignature = Signature.getInstance(SIGNATURE_ALGORITHM); dmSignature.initSign(privKey); dmSignature.update(messageToSign.getBytes()); String signature = new String(Base64.getEncoder().encode(dmSignature.sign())); return signature; } public static KeyPair generateKey() throws NoSuchAlgorithmException { KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ASSIMETRIC_ALGORITHM); keyGen.initialize(ASSIMETRIC_ALGORITHM_KEYSIZE); KeyPair key = keyGen.generateKeyPair(); return key; } public static byte[] copyBytes(byte[] src, int length) { byte[] dest = null; if (src.length == length) { dest = src; } else { dest = new byte[length]; for (int i = 0; i < length; i++) { dest[i] = (byte) src[i]; } } return dest; } private static SecretKey getPasswordBasedKey(String cipher, int keySize, char[] password) throws Exception { byte[] salt = new byte[100]; SecureRandom random = new SecureRandom(); random.nextBytes(salt); PBEKeySpec pbeKeySpec = new PBEKeySpec(password, salt, 65536, keySize); SecretKey pbeKey = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256").generateSecret(pbeKeySpec); return new SecretKeySpec(pbeKey.getEncoded(), cipher); } public static IvParameterSpec getIVSecureRandom(String algorithm) throws NoSuchAlgorithmException, NoSuchPaddingException { SecureRandom random = SecureRandom.getInstanceStrong(); byte[] iv = new byte[Cipher.getInstance(algorithm).getBlockSize()]; random.nextBytes(iv); return new IvParameterSpec(iv); } public static PublicKey getPublicKeyFromString(String publicKeyText) throws Exception { byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyText); X509EncodedKeySpec encoded = new X509EncodedKeySpec(publicKeyBytes); PublicKey publicKey = KeyFactory.getInstance(ASSIMETRIC_ALGORITHM).generatePublic(encoded); return publicKey; } public static String getMD5(String text) { byte[] md5 = DigestUtils.getMd5Digest().digest(text.getBytes(Charset.forName("UTF-8"))); String md5String = new String(Hex.encodeHex(md5)); return md5String; } }
Kapcsolódó hivatkozások
- A hozzászóláshoz be kell jelentkezni