com.oth.jasds.crypto.Crypto.java Source code

Java tutorial

Introduction

Here is the source code for com.oth.jasds.crypto.Crypto.java

Source

/*
 * 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;
    }

}