09 May 2014

Implémentation de AES en C/C++

Pour avoir eu un peu du mal à trouver une SPEC d'implémentation claire et concise sur AES quand j'en avais besoin, j'ai donc décidé de partager avec vous quelques petits détails d'implémentation qui pourraient être utiles.

Quelques points à connaître sur AES:

AES (Advenced Encryption System) successeur de DES (Digital Encryption System) est un algorithme de chiffrement symétrique ou à clé secrete par opposition aux algorithmes de chiffrements asymétrique ou à clé publique (ex: RSA, EL Gamal, etc).
AES supporte trois tailles de clés différentes: 128 bits, 192 bits et 256 bits, c'est pourquoi dans la pratique, on parle toujours de AES-128, AES-192 ou AES-256 pour préciser la taille de la clé utilisée.
AES réalise un chiffrement par bloc 128 bits, et comme tout chiffrement par bloc, AES utilise les modes (standards) de chaînage de bloc: ECB (Electronic Code Blook), CBC(Cipher Block Chaining). etc. On parlera donc de AES-128-ECB, AES-256-CBC, ... 
Et puisqu'on ne peut pas être sûr d'avoir que des blocs de 128 bits, on donc besoin de faire du padding: qui consiste à compléter le dernier bloc à 128 bits. Et pour éviter que chacun fasse son padding de son coté, des standards existent justement pour mettre tout le monde d'accord. Car c'est facile de mettre du bruit à la fin pour compléter un bloc à 128 bits, mais de l'autre coté faudrait pouvoir le détecter et l'éliminer lors du déchiffrement, sinon on violerait un des principes fondamentales de la sécurité de l'information qui est: l'intégrité.

Notations: On notera Nk le nombre de mots de 32 bits que contient une clé de chiffrement, ex: Nk = 4 pour une clé de 128 bits.

Nr le nombre de round à effectuer pour une taille de clé donnée, Nr = 10, 12, 14 respectivement pour une clé de 128, 192, 256 bits.
AES opère sur une matrice de 4x4  octets d'élément dans F256, notée state.

Implémentation:

une description de la moulinette de chiffrement AES peut se formaliser de manière suivante (en pseudo code C):

AES_Encrypt(State, K)

{

       KeyExpansion(K, RoundKeys);

       /* Addition initiale */

       AddRoundKey(State, RoundKeys[O]);

       /* Les Nr­1 rondes */

       for (r=1; i<Nr; r++) {

           SubBytes(State);

           ShiftRows(State);

           MixColumns(State);

           AddRoundKey(State, RoundKeys[r]);

       }

       /* FinalRound */

       SubBytes(State);

       ShiftRows(State);

       AddRoundKey(State, RoundKeys[Nr]);

}

En attendant de trouver un peu de temps pour décortiquer dans les détails l'implémentation cet algorithme de chiffrement symétrique qui est actuellement le plus utilisé pour le chiffrement des transactions numériques, je laisse à votre disposition une implémentation au quelle j'ai participé.
L'implémentation en question se retrouve dans le cadre d'un projet qui visait à mettre en place une espèce de calculette cryptographique implémentant plusieurs algorithmes de chiffrement (dont AES) et de hachage. (écrit en C/C++ avec une interface graphique faite avec QT)
lien du repository: https://bitbucket.org/blackhook/cryptocalc/src

21 April 2013

IPv6 ⇐⇒ IPv4 Translator for TCP

I'm Currently working in a new Project which aims to enable a machine using only the TCP/IPv6 stack to communicate with IPv4 machines seamlessly through TCP.

Technology stack:
Python: Implementation language
Scapy: for the capture, analysis, modification, creation and injection of IPv4 or IPv6 packets.  
NetFilter: especially the 'mangle' table which allow us to intercept incoming packets to TCP/IP stack, through the channel "PREROUTING".
NFQueue: The netfilter gateway ⇔ "User space" that will allow us to retrieve packages IPv4 and IPv6 in a user program from a netfilter rule.
Radvd: A demon making the dissemination of "router advertisement" for the spread of IPv6 network prefix and the router supporting the traffic to/from outside the local network.
Socat: For making TCP connections either on IPv4 or IPv6.

The repository is currently private for Academic reasons, and will be shortly available for public

19 April 2013

OTP (One Time Password) generator


I recently, worked on a project that was to develop a platform for electronic validation.
And I implemented an authentication system by OTP (using google algorithm)


OTP?:

OTP(one time password) is an authentication system, used to check a user identity without asking him his real password.
The first step is to have a secret (password) shared between the client and the server, and then every 30 sec a new OTP can be generated on both side using this secret and the current time. a generated OTP is only valid for 30 sec.

Advantage:
  - The real secret is never exchanged between the client and the server during authentication
  - In case your password is stolen, by keylogger or network sniffer for example, it is impossible to reuse it 30s after his generation.

disadvantages:
  - The main problem of this system is the time synchronization between the client and the server:
because if the server and the client is not synchronized in time (which is very likely), they can generated at the same time two different OTP, which leads to an authentication failure


OTP generator
OTP generator with color notification
On the screenshot you can see that  for a generated OTP, user is notified of the time remaining before its expiration and also the OTP is green if it is in the first 10 seconds, in yellow for the second ones and finally red if the OTP is in the last 10 seconds and will very shortly expire.
#!/usr/bin/python
import base64,time,hmac,sys, datetime
from hashlib import sha1
import struct

class otp_google:
 def __init__(self,secret):
  self._secret = secret
  
 
 def compute(self, date):
  key = base64.b32decode(self._secret,True)
  temps = int(date / 30)
  message = struct.pack('>q', temps)
  hashed = hmac.new(key, message, sha1)
  hexa = hashed.digest().encode('hex')
  lastBit = hexa[-1]
  offset = int(lastBit,16)
  offsetStart = 0 if offset == 0 else 2*offset
  offsetEnd = offsetStart + 8
  truncated = hexa[offsetStart:offsetEnd]
  token_base = int(truncated,16) & 0x7fffffff  
  token = token_base % 1000000
  return str(token).zfill(6)
#!/usr/bin/python
# -*- coding: utf-8 -*-
from Tkinter import *

import time,os,datetime,Otp

coul = ["green", "yellow", "red" ]
i = 0
secret = "ggnpvfgvmedxeroz"
OTP = Otp.otp_google(b'%s'%secret)


    
def update():
    global i
    sec = int(datetime.datetime.now().strftime("%S"))%30
    chrono.configure(text="OTP generated since: %2s sec"%sec)
    otp.configure( fg = coul[i], text=OTP.compute(int(time.time())))
    i= (sec)/10
    fen.after(1000, update)


def setSecret():
    global OTP,secret
    newSecr = entree.get()
    if not newSecr or len(newSecr)!=16:
        entree.configure(bg = "red")
        return
    secret = entree.get()
    OTP = Otp.otp_google(b'%s'%secret)
    update()
    return

fen = Tk()
fen.title("OTP generator")
L,l = 300,100
can = Canvas( width=L, height=l)
can.pack(side=TOP)
can.create_text(L/2,30,text="OTP GENERATOR",fill="Blue",font="Helvetica 20 ")
#can.bind('',start)
Label(text="Secret :").pack(side=TOP)

entree = Entry(show="*")
entree.pack(side=TOP)

Button(text=" O K ", bg = "#00f", fg= "#fff", width=10, command=setSecret).pack(side=TOP)

chrono = Label(fen, text= "OTP generated since: %2s sec"%0)
chrono.pack(side=BOTTOM)
otp=Label(fen,text="000000", font="Helvetica 50 ",fg="#ccc")
otp.pack(side=BOTTOM)
fen.mainloop()