Showing posts with label asymmetric ciphers. Show all posts
Showing posts with label asymmetric ciphers. Show all posts

Saturday, December 29, 2018

Security - Ciphers


Introduction


Today I'm going to briefly present you a topic witch points to part of security - the ciphers. At the beginning I'll show you main classification of the ciphers and next in separately chapters will describe each kind of.





As You can see there is three main type of ciphers:

  1. Simple
  2. Asymmetric
  3. Symmetric

 Simple ciphers

Substitution ciphers generally replace each character with other one or some groups of charactes are replaced with other characrer or groups of characters. Depending of compexity and advanced of ciphers one character could be replaced by single character or character wich belongs to defined list of elements.

Transposition ciphers based on changing position of the characters. There could be build appropriate matrix where number of columns could depend on secret key. Changing the order of the columns generate unreadable text for the others.

Modern ciphers are mix of Substitution and Transposition ciphers. Lets see next categories.



Asymmetric ciphers

Asymmetric cryptography is kind of cryptography wich base on private and public key. One key is used to encrypt a message and the other key is used to decrypt the message. Is not possible to execute both operation encryption and decryption using one key. Usually is recommended to use public key for encryption so only owner of the private key can decrypt the message.
Encryption algorithm should be used with padding PKCS#1 or OEAP because of security.

The asymmetric algorithms:

  • RSA
  • Diffie–Hellman (one of the key-agreement algorithms)


Below is example of using RSA algorithm with OAEP padding. I use bouncycastle library (https://www.bouncycastle.org/)



package security;

import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

/**
 *
 * @author Artur
 */
public class AsyncCipher {
    private static final String incommingMessage = "message for encryption";
   
    public static void main(String[] args)
            throws InvalidKeyException, NoSuchAlgorithmException,
            IllegalBlockSizeException, BadPaddingException,
            NoSuchProviderException, NoSuchPaddingException {
       
        long startTime = System.currentTimeMillis();
        asyncCipher(incommingMessage);
        long endTime = System.currentTimeMillis();
        System.out.println("Execution time: " + ((endTime - startTime)) + " milliseconds");
    } 
   
    public static void asyncCipher(final String inMessage)
            throws InvalidKeyException, NoSuchAlgorithmException,
            IllegalBlockSizeException, BadPaddingException,
            NoSuchProviderException, NoSuchPaddingException {
       
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

        byte[] message = inMessage.getBytes();
        Cipher rsaOaep = Cipher.getInstance("RSA/None/OAEPWithSHA1AndMGF1Padding", "BC");
        SecureRandom sr = new SecureRandom();
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");

        generator.initialize(2048, sr);

        KeyPair pair = generator.generateKeyPair();
        Key pubKey = pair.getPublic();
        Key privKey = pair.getPrivate();

        rsaOaep.init(Cipher.ENCRYPT_MODE, pubKey, sr);        
                    long startTime = System.currentTimeMillis();
                    byte[] encryptedMessage = rsaOaep.doFinal(message);
                    long endTime = System.currentTimeMillis(); 
                    System.out.println("Encryption Execution Time: " + ((endTime - startTime)) + " milliseconds; Encrypted                                message: ".concat(Base64.encodeBase64String(encryptedMessage)));

        rsaOaep.init(Cipher.DECRYPT_MODE, privKey);
        byte[] decryptedMessage = rsaOaep.doFinal(encryptedMessage);
        System.out.println("Decrypted message : ".concat(new String(decryptedMessage))); 
    }
}

Output:

Encryption Execution Time: 1 milliseconds; Encrypted message: Xby9krU99bBxdtr3ea+0tSlP0j7IySiysTmT4PTc/e2L6yIsulnagsrWYNRm59q1Vpt1fOZFJA/7IO+hwngY2ghWihhcGFRfrtPqzWp5Xc6afhg1u4iHO9RhOQc+s2Kfvg+4O7/+zNuCL4HTB4wkEdMS3qU4MPGtaD1o+MygsjPFJJoJZ/ZBn5wbIttjQGpE+Bp6ECQL70D9X8RGyYuuGvaPK9csP7ENMCCmtk0G0uPy7AKpe77A5xEOfUC9K68+af4XMHXeg+0PuhHVlsVSCG972cqlCz1vmKayumnDyzbK/eARrDL3xW54RqVAQlWQgeolcEHzapKcAc4qWuLf9Q==
Decrypted message : message for encryption
Execution time: 1584 milliseconds


I mentioned about key-agreement algorithms . This is base functionality used in SSL/TLS protocols.

Symmetric ciphers

Symmetric ciphers use the same key for encryption and decryption. There are two types of symmetric ciphers - stream and block ciphers. Below is attached diagram with the structure of symmetric ciphers.




Block ciphers split plain text in blocks which have the same size and next encrypt them one by one. Algorithm AES with CBC mode is able to mix data from different blocks. Stream ciphers work on stream of plaintext data and they do not divide it into smaller blocks.


Below is example of using AES algorithm with CBC mode. For authenticated encryption I recommend to use GCM mode.


package security;

import com.google.api.client.repackaged.org.apache.commons.codec.binary.Base64;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.util.encoders.Hex;


/**
 *
 * @author Artur
 */
public class SyncCipher {
     private static final String incommingMessage = "message for encryption";
    
    public static void main(String[] args) 
            throws InvalidKeyException, NoSuchAlgorithmException, 
            IllegalBlockSizeException, BadPaddingException, 
            NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException {
        
        long startTime = System.currentTimeMillis();
        syncCipher(incommingMessage);
        long endTime = System.currentTimeMillis();
        System.out.println("Total Execution Time: " + ((endTime - startTime)) + " milliseconds");
    }  
    
    public static void syncCipher(final String inMessage) 
            throws InvalidKeyException, NoSuchAlgorithmException, 
            IllegalBlockSizeException, BadPaddingException, 
            NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException {
        
        java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

        IvParameterSpec iv = new IvParameterSpec("myEncIntVector_1".getBytes("UTF-8"));
        SecretKeySpec skeySpec = new SecretKeySpec("myEncryptionKey1".getBytes("UTF-8"), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        long startTime = System.currentTimeMillis();
        byte[] encryptedMessage = cipher.doFinal(inMessage.getBytes());  
        long endTime = System.currentTimeMillis();
        System.out.println("Encryption Execution Time: " + ((endTime - startTime)) + " milliseconds; Encrypted message: ".concat(Base64.encodeBase64String(encryptedMessage)));

        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
        byte[] decryptedMessage = cipher.doFinal(encryptedMessage);
        System.out.println("Decrypted message : ".concat(new String(decryptedMessage)));  
    }
}


Encryption Execution Time: 0 milliseconds; Encrypted message: 5YWJup+o7SRd3o1rtqS1OtTCx7RpY8og8WDBZVXRNZM=
Decrypted message : message for encryption
Total Execution Time: 339 milliseconds