Ousret/Picross-L3S6

View on GitHub
class/crypt.class.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'openssl'
require 'faker'
require 'yaml'

# Author::    Bien-CV https://github.com/Bien-CV
# License::   MIT Licence
#
# https://github.com/Ousret/Picross-L3S6
#
#*Créer une instance de cette classe, en donnant en paramètre un mot de passe déterminé par lutilisateur,
#*utilise le PKCS5 pour sécuriser le mot de passe.
#*Appeler une instance de cette classe avec les méthodes encrypt(data) et decrypt(data) cryptera ou décryptera
#*les données fournies en paramètre grace à de l AES 128bits GCM en se servant du mot de passe crypté par le PKCS5
#*en clé de cryptage.
#

class Crypt

    #@nbOfEncrypt
    #@nbOfDecrypt
    #@psw
    #@processedPsw
    #@cipherType
    #@iv

    #Accesseurs
    attr_reader :nbOfEncrypt
    attr_reader :nbOfDecrypt

    #Prévoir de rendre privé la méthode hashLeMotDePasse

    #Empêche l'utilisation de la méthode new pour payer nos hommages à monsieur Jacoboni
    private_class_method :new

    #Méthode de création d'instance de la classe Crypt.
    #
    # * *Arguments*    :
    #   - +unPassword+ -> le mot de passe utilisé comme clé
    #   - +encryptionMethod+ -> La méthode d'encryption à utiliser, toutes ne sont pas supportées. ( cf https://docs.google.com/document/d/1Hdzg2B-U0fL_KFjIpdfWqLR6xUaBIzQuEXP7pZsM3V4/pub )
    #   - +chosenIv+ -> Le vecteur d'initialisation à utiliser.
    # * *Return value* :
    #   - Une nouvelle instance de la classe Crypt.
    # * *Sample code* :
    #   - myCipher = Crypt.creer("passwordThing")
    #   - myCipher = Crypt.creer("passwordThing",'aes-128-gcm',"myOwnIV")
    def Crypt.creer(unPassword,encryptionMethod='AES-128-CBC')
        new(unPassword,encryptionMethod)
    end

    #Méthode de création d'instance de la classe Crypt.
    #
    # * *Arguments*    :
    #   - +unPassword+ -> le mot de passe utilisé comme clé
    #   - +chosenIv+ -> Le vecteur d'initialisation à utiliser.
    # * *Return value* :
    #   - Une nouvelle instance de la classe Crypt.
    # * *Usage* :
    #   - myCipher = Crypt.creerAes256GCM("passwordThing")
    #   - myCipher = Crypt.creerAes256GCM("passwordThing","myOwnIV")
    def Crypt.creerAes256GCM(unPassword)
        new(unPassword,'AES-128-CBC')
    end

    #Méthode d'initialisation utilisée lors de la création d'instance.
    #
    #
    # * *Arguments*    :
    #   - +unPassword+ -> le mot de passe utilisé comme clé
    #   - +encryptionMethod+ -> La méthode d'encryption à utiliser, toutes ne sont pas supportées. ( cf https://docs.google.com/document/d/1Hdzg2B-U0fL_KFjIpdfWqLR6xUaBIzQuEXP7pZsM3V4/pub )
    #   - +chosenIv+ -> Le vecteur d'initialisation à utiliser.
    # * *Return value* :
    #   - Une nouvelle instance de la classe Crypt.
    def initialize(password,encryptionMethod)

        #Est le mot de passe choisi et utilisé comme clé de cryptage, il est choisi lors de la création d'instance.
        @psw = password

        #Contient le hash du mot de passe
        @processedPsw = hashLeMotDePasse()
        #Type d'encryptage choisi, AES 128 bits GCM par défault : Attention, certains encryptages ne seront pas supportés
        @cipherType = encryptionMethod
        #Vecteur d'initialisation de l'algorithme de cryptage, contient une valeur par défaut.

        @nbOfEncrypt=0
        @nbOfDecrypt=0

    end

    #Methode qui hash le mot de passe en utilisant un sel aléatoire et PBKDF2
    #Est uniquement appelée lors de l'initialisation d'une nouvelle instance.
    #
    # * *Return value* :
    #   - La clé de cryptage calculée selon le mot de passe
    def hashLeMotDePasse
        #Le salt ajoute une composante aléatoire évitant de casser l'algo d'encryption par Rainbow Tables.
        salt = OpenSSL::Random.random_bytes(32)
        iter = 64
        key_len = 256
        key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(@psw, salt, iter, key_len)
        return key
    end

    #Methode qui encrypte une donnée en utilisant le type d'encryption précisé lors de la création d'instance,
    #le hash du mot de passe précisé lors de la création d'instance,
    #le IV du mot de passe précisé lors de la création d'instance.
    #
    #Incrémente la variable d'instance nbOfEncrypt, qui compte le nombre d'encryptions effectuées par l'encodeur/décodeur.
    #
    # * *Arguments*    :
    #   - +dataToEncrypt+ -> la donnée à encrypter, qui est ensuite traduite en YAML
    # * *Return value* :
    #   - La chaîne encryptée
    #
    # * *Usage* :
    #   - myCryptInstance.encrypt(objectToBeEncrypted)
    def encrypt(dataToEncrypt)
        #JSON.parse(string)
        yamlString=dataToEncrypt.to_yaml
        cipher = OpenSSL::Cipher.new(@cipherType)

        cipher.encrypt
        cipher.key = @processedPsw
        cipher.iv = cipher.random_iv

        encrypted = cipher.update(yamlString) + cipher.final
        #tag = cipher.auth_tag

        #Indique le nombre de fois que la méthode encrypt a été utilisée
        @nbOfEncrypt=@nbOfEncrypt+1

        return encrypted
    end

    #Methode qui décrypte une donnée YAML encryptée en utilisant le type d'encryption précisé lors de la création d'instance,
    #le hash du mot de passe précisé lors de la création d'instance,
    #le IV du mot de passe précisé lors de la création d'instance.
    #
    #Incrémente la variable d'instance nbOfDecrypt, qui compte le nombre de décryptions effectuées par l'encodeur/décodeur.
    #
    # * *Arguments*    :
    #   - +dataToDecrypt+ -> l'objet YAML encrypté à décrypter
    # * *Return value* :
    #   - L'objet décrypté
    # * *Usage* :
    #   - myCryptInstance.decrypt(encryptedObject)
    def decrypt(dataToDecrypt)
        decipher = OpenSSL::Cipher.new(@cipherType)
        decipher.decrypt
        decipher.key = @processedPsw
        decipher.iv = @iv

        plain = decipher.update(dataToDecrypt) + decipher.final

        #Indique le nombre de fois que la méthode decrypt a été utilisée
        @nbOfDecrypt=@nbOfDecrypt+1
        puts "Near end decrypt with #{plain}"
        return YAML.load(plain)
    end


end