Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.oth.jasds.crypto; import com.oth.jasds.submodules.model.FileKey; import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.lang.reflect.Field; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Security; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.MGF1ParameterSpec; import java.util.logging.Level; import java.util.logging.Logger; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.ShortBufferException; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource; import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.crypto.AsymmetricBlockCipher; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.encodings.PKCS1Encoding; import org.bouncycastle.crypto.engines.RSAEngine; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.util.PrivateKeyFactory; import org.bouncycastle.crypto.util.PublicKeyFactory; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMDecryptorProvider; import org.bouncycastle.openssl.PEMEncryptedKeyPair; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder; import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; import org.bouncycastle.operator.InputDecryptorProvider; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo; import org.bouncycastle.pkcs.PKCSException; import org.bouncycastle.util.encoders.Base64Encoder; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import sun.security.util.Password; /** * * @author vladas-m */ public class Crypto implements CryptoIF { private static final int blockSize = 16; public Crypto() { Security.addProvider(new BouncyCastleProvider()); try { // disable key strength limitation, which is set to 128bit keys by default Field f = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted"); f.setAccessible(true); f.set(null, java.lang.Boolean.FALSE); } catch (Exception e) { e.printStackTrace(); } } @Override public KeyPair generateKeyPair(int size) { try { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); keyGen.initialize(size); return keyGen.generateKeyPair(); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } return null; } @Override public byte[] generateSecureRandomByteArray(int size) { SecureRandom sr = new SecureRandom(); byte[] bytes = new byte[size]; sr.nextBytes(bytes); return bytes; } @Override public byte[] encryptFile(byte[] input, FileKey fileKey) { try { Cipher encCipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC"); SecretKey keyValue = new SecretKeySpec(StringToByteArray(fileKey.getKey()), "AES"); AlgorithmParameterSpec IVspec = new IvParameterSpec(StringToByteArray(fileKey.getIv())); encCipher.init(Cipher.ENCRYPT_MODE, keyValue, IVspec); ByteArrayInputStream in = new ByteArrayInputStream(input); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buffer = new byte[blockSize]; int noBytes = 0; byte[] cipherBlock = new byte[encCipher.getOutputSize(buffer.length)]; int cipherBytes; while ((noBytes = in.read(buffer)) != -1) { cipherBytes = encCipher.update(buffer, 0, noBytes, cipherBlock); out.write(cipherBlock, 0, cipherBytes); } //always call doFinal cipherBytes = encCipher.doFinal(cipherBlock, 0); out.write(cipherBlock, 0, cipherBytes); out.flush(); byte[] enc = out.toByteArray(); out.close(); in.close(); return enc; /* byte[] cipherBlock = new byte[encCipher.getOutputSize(input.length)]; int cipherBytes; ByteArrayOutputStream out = new ByteArrayOutputStream(); int i; for(i = 0; (i+1)*blockSize < input.length; i++){ cipherBytes = encCipher.update(input, i*blockSize, blockSize, cipherBlock); out.write(cipherBlock, 0, cipherBytes); } cipherBytes = encCipher.doFinal(cipherBlock, i*blockSize); out.write(cipherBlock, 0 , cipherBytes); byte[] enc = out.toByteArray(); out.close(); return enc; */ } catch (InvalidKeyException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (InvalidAlgorithmParameterException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchProviderException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchPaddingException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (ShortBufferException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (IllegalBlockSizeException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (BadPaddingException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } return null; } @Override public byte[] decryptFile(byte[] input, byte[] fileKey, byte[] iv, byte[] aad) { try { //Cipher decCipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC"); Cipher decCipher = Cipher.getInstance("AES/GCM/NoPadding", "BC"); SecretKey keyValue = new SecretKeySpec(fileKey, "AES"); AlgorithmParameterSpec IVspec = new IvParameterSpec(iv); AlgorithmParameterSpec GCMspec = new GCMParameterSpec(8 * aad.length, iv); //decCipher.init(Cipher.DECRYPT_MODE, keyValue, IVspec); //decCipher.updateAAD(aad); decCipher.init(Cipher.DECRYPT_MODE, keyValue, GCMspec); byte[] ciperBytes = new byte[input.length + aad.length]; System.arraycopy(input, 0, ciperBytes, 0, input.length); System.arraycopy(aad, 0, ciperBytes, input.length, aad.length); ByteArrayInputStream in = new ByteArrayInputStream(ciperBytes); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buffer = new byte[blockSize]; int noBytes = 0; byte[] cipherBlock = new byte[decCipher.getOutputSize(ciperBytes.length)]; int cipherBytes; while ((noBytes = in.read(buffer)) != -1) { cipherBytes = decCipher.update(buffer, 0, noBytes, cipherBlock); out.write(cipherBlock, 0, cipherBytes); } //always call doFinal cipherBytes = decCipher.doFinal(cipherBlock, 0); out.write(cipherBlock, 0, cipherBytes); out.flush(); byte[] enc = out.toByteArray(); out.close(); in.close(); return enc; /* byte[] cipherBlock = new byte[decCipher.getOutputSize(input.length)]; int cipherBytes = 0; ByteArrayOutputStream out = new ByteArrayOutputStream(); int i; for(i = 0; (i+1)*blockSize < input.length; i++){ cipherBytes = decCipher.update(input, i*blockSize, blockSize, cipherBlock); out.write(cipherBlock, 0, cipherBytes); } cipherBytes = decCipher.doFinal(cipherBlock, i*blockSize); out.write(cipherBlock, 0 , cipherBytes); byte[] dec = out.toByteArray(); out.close(); return dec; */ } catch (NoSuchAlgorithmException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchProviderException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchPaddingException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (InvalidKeyException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (InvalidAlgorithmParameterException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (ShortBufferException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (IllegalBlockSizeException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (BadPaddingException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } return null; } @Override public String encryptFileKey(byte[] fileKey, PublicKey pubKey) { try { AsymmetricBlockCipher e = new RSAEngine(); e = new PKCS1Encoding(e); AsymmetricKeyParameter pub = (AsymmetricKeyParameter) PublicKeyFactory.createKey(pubKey.getEncoded()); e.init(true, pub); byte[] encFk = e.processBlock(fileKey, 0, fileKey.length); BASE64Encoder b64 = new BASE64Encoder(); return b64.encode(encFk); } catch (IOException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (InvalidCipherTextException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } return null; } @Override public byte[] decryptFileKey(String fileKey, PrivateKey prvKey) { try { AsymmetricBlockCipher e = new RSAEngine(); e = new PKCS1Encoding(e); AsymmetricKeyParameter pub = (AsymmetricKeyParameter) PublicKeyFactory.createKey(prvKey.getEncoded()); e.init(true, pub); BASE64Decoder b64 = new BASE64Decoder(); byte[] fk = b64.decodeBuffer(fileKey); byte[] decfk = e.processBlock(fk, 0, fk.length); return decfk; } catch (IOException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (InvalidCipherTextException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } return null; } @Override public String ByteArrayToString(byte[] fileKey) { BASE64Encoder enc = new BASE64Encoder(); return enc.encode(fileKey); } @Override public byte[] StringToByteArray(String fileKey) { try { BASE64Decoder dec = new BASE64Decoder(); return dec.decodeBuffer(fileKey); } catch (IOException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } return null; } public byte[] decryptFileKey(String filekey, String privateKey) { try { BASE64Decoder b64 = new BASE64Decoder(); ByteArrayInputStream in = new ByteArrayInputStream(privateKey.getBytes()); PEMParser pemRd = new PEMParser(new InputStreamReader(in)); PrivateKey prvKey = null; Object obj = pemRd.readObject(); JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); if (obj instanceof PKCS8EncryptedPrivateKeyInfo) { PKCS8EncryptedPrivateKeyInfo pkcs8 = (org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo) obj; JceOpenSSLPKCS8DecryptorProviderBuilder jce = new JceOpenSSLPKCS8DecryptorProviderBuilder() .setProvider("BC"); InputDecryptorProvider decProv = jce.build("Qwer1234!".toCharArray()); PrivateKeyInfo pkinfo = pkcs8.decryptPrivateKeyInfo(decProv); prvKey = converter.getPrivateKey(pkinfo); } else { throw new Exception("party"); } Cipher rsaCipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING"); rsaCipher.init(Cipher.DECRYPT_MODE, prvKey, new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT)); //rsaCipher.init(Cipher.DECRYPT_MODE, prvKey); byte[] decfk = rsaCipher.doFinal(b64.decodeBuffer(filekey)); /* AsymmetricBlockCipher e = new RSAEngine(); e = new PKCS1Encoding(e); AsymmetricKeyParameter prv = (AsymmetricKeyParameter) PrivateKeyFactory.createKey(prvKey.getEncoded()); e.init(true, prv); byte[] fk = b64.decodeBuffer(filekey); byte[] decfk = e.processBlock(fk, 0, fk.length); */ System.out.println("done"); return decfk; } catch (IOException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (InvalidCipherTextException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (OperatorCreationException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (PKCSException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (IllegalBlockSizeException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (BadPaddingException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (InvalidKeyException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchProviderException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchPaddingException ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } catch (Exception ex) { Logger.getLogger(Crypto.class.getName()).log(Level.SEVERE, null, ex); } return null; } }