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


Tuesday, November 6, 2018

XML Schema

Objectives


Today I'm going to introduce you in subject of creating, visualization and using XSD. XML Schema was created by W3C for creating XML structure definition. This is a kind of contract which could be used in many solutions. One of the best usages is creating data model in WSDL (Web service contract)

Below is personal data's XSD structure which contains simple and complex types. There are diverse types of restrictions:

  • simple:  minOccurs, maxOccurs
  • complex: <xsd:restriction base="xsd:string"> 

There is also example of inheritance:  <xsd:extension base="as:document">

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:as="https://www.linkedin.com/in/artur-scigajlo-9144092/"
            targetNamespace="https://www.linkedin.com/in/artur-scigajlo-9144092/"
            xmlns:iso639-2="http://lcweb.loc.gov/standards/iso639-2/"
            elementFormDefault="qualified">
           
    <xsd:import namespace="http://lcweb.loc.gov/standards/iso639-2/"  schemaLocation="http://files.dnb.de/standards/xmetadiss/iso639-2.xsd"/>
               
               
   <xsd:complexType name="personalData">
        <xsd:sequence>
            <xsd:element name="workerId" type="xsd:string" minOccurs="1" maxOccurs="1"/>
            <xsd:element name="worker" type="as:worker" minOccurs="1" maxOccurs="1"/>
            <xsd:element name="partA" type="as:documentPartA" minOccurs="1" maxOccurs="unbounded"/>
            <xsd:element name="partB" type="as:documentPartB" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
             
  <xsd:complexType name="worker">
        <xsd:sequence>
            <xsd:element name="lastName" type="xsd:string" minOccurs="1" maxOccurs="1"/>
            <xsd:element name="firstName" type="xsd:string" minOccurs="1" maxOccurs="1"/>
            <xsd:choice>
                <xsd:element name="personId">
                   <xsd:simpleType>
                    <xsd:restriction base="xsd:string">
                      <xsd:minLength value="10"/>
                      <xsd:maxLength value="26"/>
                    </xsd:restriction>
                  </xsd:simpleType>
                </xsd:element>
                <xsd:element name="otherTypeOfDocument">
                    <xsd:complexType>
                        <xsd:sequence>
                          <xsd:element name="type" type="xsd:string" minOccurs="1" maxOccurs="1"/>
                          <xsd:element name="number" type="xsd:string" minOccurs="1" maxOccurs="1"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:choice>
        </xsd:sequence>
    </xsd:complexType>
   
        <xsd:complexType name="document">
            <xsd:sequence>
                <xsd:element name="documentId" type="xsd:string" minOccurs="1" maxOccurs="1"/>
                <xsd:element name="title" type="as:title" minOccurs="0" maxOccurs="1"/>
                <xsd:element name="createdDate" type="xsd:date" minOccurs="1" maxOccurs="1"/>
                <xsd:element name="documentType" type="as:documentType" minOccurs="0" maxOccurs="1"/>
            </xsd:sequence>
    </xsd:complexType>
   
       <xsd:complexType name="title">
        <xsd:simpleContent>
            <xsd:extension base="xsd:string">
                <xsd:attribute name="language" type="iso639-2:RegisteredCodeType" use="optional"/>
            </xsd:extension>
        </xsd:simpleContent>
    </xsd:complexType>
   
      <xsd:complexType name="documentType">
        <xsd:sequence>
            <xsd:element name="type" minOccurs="1" maxOccurs="1">
              <xsd:simpleType>
                <xsd:restriction base="xsd:string">
                  <xsd:enumeration value="driverLicence"/>
                  <xsd:enumeration value="passport"/>
                  <xsd:enumeration value="insuranceNo"/>
                  <xsd:enumeration value="other"/>
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
            <xsd:element name="numer" type="xsd:string" minOccurs="1" maxOccurs="1"/>
        </xsd:sequence>
      </xsd:complexType>
   
    <xsd:complexType name="documentPartA">
        <xsd:complexContent>
            <xsd:extension base="as:document">
                <xsd:attribute name="subType" use="required">
                    <xsd:simpleType>
                        <xsd:restriction base="xsd:string">
                          <xsd:pattern value="^[ABC]\d{2}$"/>
                        </xsd:restriction>
                    </xsd:simpleType>
                </xsd:attribute>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
   
    <xsd:complexType name="documentPartB">
        <xsd:complexContent>
            <xsd:extension base="as:document">
                <xsd:attribute name="subType" use="required">
                    <xsd:simpleType>
                        <xsd:restriction base="xsd:string">
                          <xsd:pattern value="^[XYZ]\d{2}$"/>
                        </xsd:restriction>
                    </xsd:simpleType>
                </xsd:attribute>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>   

</xsd:schema>




Data model visualization

There are existing useful applications to help creating XSD. Some of them have a plugins to generate visualization diagrams. Below is our schema's diagram.





Genarating XML file base on XSD Schema


I created project in Netbeans.





I imported XSD and generated java classes automatically.







We can see the generated classes





The main class is used to generate XML file









Below is java class

/*
 * 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 artur.scigajlo;

import artur.scigajlo.personalData.DocumentPartA;
import artur.scigajlo.personalData.DocumentType;
import artur.scigajlo.personalData.PersonalData;
import artur.scigajlo.personalData.Title;
import artur.scigajlo.personalData.Worker;
import artur.scigajlo.personalData.Worker.OtherTypeOfDocument;
import com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;

/**
 *
 * @author a.scigajlo
 */
public class PersonalDataProject {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws PropertyException, JAXBException {
              PersonalData ao = new PersonalData();
        ao.setWorkerId("worker_01");
     
        Worker worker = new Worker();
        worker.setFirstName("Jon");
        worker.setLastName("Black");
     
        OtherTypeOfDocument otherDoc = new OtherTypeOfDocument();
        otherDoc.setNumber("AAA123456");
        otherDoc.setType("otherPersonId"); 
        worker.setOtherTypeOfDocument(otherDoc);     
     
        ao.setWorker(worker);
     
     
        DocumentPartA docA1 = new DocumentPartA();
        docA1.setCreatedDate(XMLGregorianCalendarImpl.createDate(2018,3,4,0));
        docA1.setDocumentId("docID-714");
     
        Title t1 = new Title();
        t1.setLanguage("pol");
        t1.setValue("hello.pdf");
        docA1.setTitle(t1);
     
        DocumentType dt1 = new DocumentType();
        dt1.setNumer("AEC12");
        dt1.setType("driverLicence");
        docA1.setDocumentType(dt1);
     
        ao.getPartA().add(docA1);
     
        DocumentPartA docA2 = new DocumentPartA();
        docA2.setCreatedDate(XMLGregorianCalendarImpl.createDate(2018,5,14,0));
        docA2.setDocumentId("annexID-318");
     
        Title t2 = new Title();
        t2.setLanguage("pol");
        t2.setValue("test.pdf");
        docA2.setTitle(t2);
     
        DocumentType dt2 = new DocumentType();
        dt2.setNumer("AEC12");
        dt2.setType("driverLicence");
        docA2.setDocumentType(dt2);
     
        ao.getPartA().add(docA2);
         
        JAXBContext jaxbContext = JAXBContext.newInstance(PersonalData.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
     
     
        //ZAPIS DO PLIKU
        jaxbMarshaller.marshal(ao, new File("c:\\tmp\\PersonalData.xml"));
    }
 
}


Finally we get XML file




Thursday, August 16, 2018

LinkedList custom implementation in Java

Objectives


Today i'm going to introduce you in my custom LinkedList implementation.Below is prepared diagram which shows internal class's structure. Every Node handles reference to next Node. The last Node has an empty reference. There are two fields which hold reference to first and last Nodes.




Below is internal Node's structure which holds items and references.


private class Node<T extends Object>{
        Node<T> next;
        T object;
     
        public Node(T object){
            this.next = null;
            this.object = object;
        }
     
        public Node(T object, Node<T> next){
            next.setNext(this);
            this.next = null;
            this.object = object;
        }

        public Node<T> getNext() {
            return next;
        }

        public void setNext(Node<T> next) {
            this.next = next;
        }

        public T getObject() {
            return object;
        }

        public void setObject(T object) {
            this.object = object;
        }     
     
    }

Thursday, July 19, 2018

HashMap custom implementation

Objectives


HashMap is array of buckets to store linkedList's simple structure. Each linkedList consists of agregated in key-value ernty objects with additional references to next entry object. Very important is to create method to point correct Bucket.

Below is diagram which shows inserting entries to HashMap process.




Entry structure


Below is entry structure which implements Map.Entry interface.


    static class Entry<K,V> implements Map.Entry<K,V> {
        private K key;
        private V value;
        private Entry<K,V> next;
        public Entry(K key, V value){
            this.key = key;
            this.value = value;       
        }
        public Entry(K key, V value, Entry<K,V> next){
            this.key = key;
            this.value = value;
            this.next = next;
        }
        @Override
        public K getKey() {
            return key;
        }
        @Override
        public V getValue() {
            return value;
        }
        @Override
        public V setValue(V v) {
            this.value = v;
            return this.value;
        }
        public Entry<K, V> getNext() {
            return next;
        }
        public void setNext(Entry<K, V> next) {
            this.next = next;
        }         
    }


Bucket

Very important aspect is to create appropriate method to calculate bucket. The method has only one incoming parameter - the calculated hashCode base on key.

public static int calculateIndex(int hash) {
        return hash & (capacity-1);
    }

Main Class

Below is full source code.  
package artsci.pl;

import java.util.Map;

/**
 *
 * @author Artur
 */
public class MyHashMap <K, V> {
    private Entry<K,V>[] table;
    private final static int capacity = 16;

    public MyHashMap(){
       table = new Entry[capacity];
    }


    public void put(K key, V value){
       if(key==null)
           return;
   
       int hash=key.hashCode();
       int index = calculateIndex(hash);
   
       if(table[index] == null){
           table[index] = new Entry(key, value);
       }else{
           boolean isNodeExists = true;
           Entry currentNode = table[index];
       
           while (currentNode != null && isNodeExists) {
                if(currentNode.getKey().hashCode() == hash && key.equals(currentNode.getKey())){
                    currentNode.setValue(value);
                    break;
                }           
           
                if(currentNode.getNext() != null){
                    currentNode = currentNode.getNext();
                }else{
                    isNodeExists = false;
                    table[index] = new Entry(key, value, table[index]);
                }
            }       
       }
    }

   

    public V get(K key){
       if(key==null)
           return null;
   
       int hash=key.hashCode();
       int index = calculateIndex(hash);
       boolean isNodeExists = true;
       V out = null;
   
       if(table[index] != null){
           Entry currentNode = table[index];
   
           while (currentNode != null && isNodeExists) {
                if(currentNode.getKey().hashCode() == hash && key.equals(currentNode.getKey())){
                    out = (V)currentNode.getValue();
                }           
           
                if(currentNode.getNext() != null){
                    currentNode = currentNode.getNext();
                }else{
                    isNodeExists = false;
                }
            }   
       }
       return out;
    }

    public static int calculateIndex(int hash) {
        return hash & (capacity-1);
    }

    public String toString(){
        String out = "";           
        for(Entry currentNode : table){
            boolean isNodeExists = true;       
       
            while (currentNode != null && isNodeExists) {
                out += "["+currentNode.getKey()+";"+currentNode.getValue()+"]";
                if(currentNode.getNext() != null){
                    currentNode = currentNode.getNext();
                }else{
                    isNodeExists = false;
                }
            }   
        }   
        return out;
    }

    public int size(){
        int out = 0;       
        for(Entry currentNode : table){
            boolean isNodeExists = true;       
       
            while (currentNode != null && isNodeExists) {
                out++;           
                if(currentNode.getNext() != null){
                    currentNode = currentNode.getNext();
                }else{
                    isNodeExists = false;
                }
            }         
        }           
        return out;
    }


    static class Entry<K,V> implements Map.Entry<K,V> {
        private K key;
        private V value;
        private Entry<K,V> next;

        public Entry(K key, V value){
            this.key = key;
            this.value = value;         
        }

        public Entry(K key, V value, Entry<K,V> next){
            this.key = key;
            this.value = value;
            this.next = next;
        }

        @Override
        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public V setValue(V v) {
            this.value = v;
            return this.value;
        }

        public Entry<K, V> getNext() {
            return next;
        }

        public void setNext(Entry<K, V> next) {
            this.next = next;
        }   
   
    }
}

Test Class

package artsci.pl;

import org.junit.Test;
import static org.junit.Assert.*;

/**
 *
 * @author Artur
 */
public class MyHashMapTest {

    public MyHashMapTest() {
    }

    @Test
    public void testMethod() {
        MyHashMap <String, String> map = new MyHashMap <String, String>();
   
        for(int i = 0; i< 30; i++){   
            String key = "KEY_"+i;
            map.put(key, "VALUE_".concat(String.valueOf(i)));
            System.out.println("Key: "+key+" is in bucket: "+MyHashMap.calculateIndex(key.hashCode()) );       
        }           
   
        System.out.println("Size: "+map.size());   
        assertTrue(map.size() == 30);
   
    }

}


And the result is below:

Testsuite: artsci.pl.MyHashMapTest
Key: KEY_0 is in bucket: 0
Key: KEY_1 is in bucket: 1
Key: KEY_2 is in bucket: 2
Key: KEY_3 is in bucket: 3
Key: KEY_4 is in bucket: 4
Key: KEY_5 is in bucket: 5
Key: KEY_6 is in bucket: 6
Key: KEY_7 is in bucket: 7
Key: KEY_8 is in bucket: 8
Key: KEY_9 is in bucket: 9
Key: KEY_10 is in bucket: 15
Key: KEY_11 is in bucket: 0
Key: KEY_12 is in bucket: 1
Key: KEY_13 is in bucket: 2
Key: KEY_14 is in bucket: 3
Key: KEY_15 is in bucket: 4
Key: KEY_16 is in bucket: 5
Key: KEY_17 is in bucket: 6
Key: KEY_18 is in bucket: 7
Key: KEY_19 is in bucket: 8
Key: KEY_20 is in bucket: 14
Key: KEY_21 is in bucket: 15
Key: KEY_22 is in bucket: 0
Key: KEY_23 is in bucket: 1
Key: KEY_24 is in bucket: 2
Key: KEY_25 is in bucket: 3
Key: KEY_26 is in bucket: 4
Key: KEY_27 is in bucket: 5
Key: KEY_28 is in bucket: 6
Key: KEY_29 is in bucket: 7
Size: 30
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0,071 sec