Jump to content

OpenSSL Compliance - (Moved)


Go to solution Solved by Radix,

Recommended Posts

Posted (edited)

Greetings! (I think it needs its own topic)

I'm having problem with application integration, more precisely OpenSSL and OpenSSL-PHP. How does the Crypt UDF key derivation work? I mean, I noticed that it uses MD5 as a hash, but I didn't understand how to reproduce for example in OpenSSL. I mean, I really need an AES or even 3DES based encryption tool that is PHP/OpenSSL compatible.

The command:

openssl enc -d -aes-128-cbc -md md5 -k 12345 < file.ext

does not decrypt* the command:

encryptcli -e -in file.ext -psw 12345


It results in an error.

https://github.com/pedroalbanese/encryptcli is not compatible with OpenSSL

How to proceed?

Thanks in advance and sorry bad English.

Edited by Radix
Posted (edited)

I know how to use OpenSSL. My question is about the integration of UDF Crypt with the OpenSSL (legacy) reference.

I need an OpenSSL compatible GUI in AutoIt, similar to the example given:

 

#NoTrayIcon
#include <Crypt.au3>
#include <cmdline.au3>

If Not StringInStr($CmdLineRaw, "in") Or Not StringInStr($CmdLineRaw, "psw") Or $CmdLineRaw == "" Then
    ConsoleWrite("File Encryption Tool - ALBANESE Lab " & Chr(184) & " 2018-2020" & @CRLF & @CRLF) ;
    ConsoleWrite("Usage: " & @CRLF) ;
    ConsoleWrite("   " & @ScriptName & " -e|d --in <file.ext> --alg <algorithm> --psw <password>" & @CRLF & @CRLF) ;
    ConsoleWrite("Commands: " & @CRLF) ;
    ConsoleWrite("   -e: Encrypt " & @CRLF) ;
    ConsoleWrite("   -d: Decrypt" & @CRLF & @CRLF) ;
    ConsoleWrite("Parameters: " & @CRLF) ;
    ConsoleWrite("   /alg: Algorithm" & @CRLF) ;
    ConsoleWrite("   /in : Input file" & @CRLF) ;
    ConsoleWrite("   /out: Output file (Optional [*])" & @CRLF) ;
    ConsoleWrite("   /psw: Password" & @CRLF & @CRLF) ;
    ConsoleWrite("   [*] If no output is specified, the input file will be overwritten." & @CRLF & @CRLF) ;
    ConsoleWrite("Algorithms:" & @CRLF) ;
    ConsoleWrite("   3DES, AES-128 (Default), AES-192, AES-256, DES, RC2, RC4" & @CRLF) ;
    Exit
Else
    If _CmdLine_KeyExists('alg') Then
        Local $algo = _CmdLine_Get('alg')
        If $algo = "3DES" Then
            $alg = $CALG_3DES
        ElseIf $algo = "AES-128" Then
            $alg = $CALG_AES_128
        ElseIf $algo = "AES-192" Then
            $alg = $CALG_AES_192
        ElseIf $algo = "AES-256" Then
            $alg = $CALG_AES_256
        ElseIf $algo = "DES" Then
            $alg = $CALG_DES
        ElseIf $algo = "RC2" Then
            $alg = $CALG_RC2
        ElseIf $algo = "RC4" Then
            $alg = $CALG_RC4
        Else
            ConsoleWrite("Error: Unknown Algorithm." & @CRLF) ;
            Exit
        EndIf
    Else
        $alg = $CALG_AES_128
    EndIf
    Local $file = _CmdLine_Get('in')
    Local $file2 = _CmdLine_Get('out')
    Local $psw = _CmdLine_Get('psw')
EndIf

If _CmdLine_KeyExists('out') Then
    Local $file2 = _CmdLine_Get('out')
Else
    Local $file2 = $file
EndIf

If FileExists($file) Then
    If $CmdLine[0] > 1 And $CmdLine[1] == "-e" Or $CmdLine[1] == "-d" Then
        $full = FileRead($file)
        If $CmdLine[1] == "-e" Then
            FileOpen($file2, 2)
            FileWrite($file2, StringEncrypt(True, $full, $psw))
        ElseIf $CmdLine[1] == "-d" Then
            FileOpen($file2, 2)
            FileWrite($file2, StringEncrypt(False, $full, $psw))
        EndIf
    EndIf
Else
    ConsoleWrite("Error: """ & $file & """ not found." & @CRLF)  ;
EndIf

Func StringEncrypt($bEncrypt, $sData, $sPassword)
    _Crypt_Startup() ; Start the Crypt library.
    Local $vReturn = ''
    If $bEncrypt Then ; If the flag is set to True then encrypt, otherwise decrypt.
        $vReturn = _Crypt_EncryptData($sData, $sPassword, $alg)
    Else
        $vReturn = _Crypt_DecryptData($sData, $sPassword, $alg)
    EndIf
    _Crypt_Shutdown() ; Shutdown the Crypt library.
    Return $vReturn
EndFunc   ;==>StringEncrypt

 

This example uses AES128 as the default, and is based on UDF Crypt. It happens that I don't know how keys are derived in this UDF. I think I just need this information. How to decrypt it?

thiscode -e -in file.ext -psw 12345

Assuming the key derivation is based on MD5, this command should decrypt:
 

openssl enc -d -aes-128-cbc -md md5 -k 12345 < file.ext

But don't work.

cmdline.au3

Edited by Radix
  • Solution
Posted (edited)

It worked fine:

You need to pass 3 arguments: InputFile, Output, 16-byte Key in ASCII, that need to be converted to Hex and the file will decrypt by: (pass abcdefghijuklmno)

; ====================================================
; ============= Encryption Tool With CLI =============
; ====================================================
; AutoIt version: 3.3.12.0
; Language:       English
; Author:         Pedro F. Albanese
; Modified:       -
;
; ----------------------------------------------------------------------------
; Script Start
; ----------------------------------------------------------------------------

#NoTrayIcon
#include <Crypt.au3>
#include <cmdline.au3>

Global Const $KP_MODE = 4
Global Const $CRYPT_MODE_CBC = 2

_Crypt_Startup()

If Not StringInStr($CmdLineRaw, "in") Or Not StringInStr($CmdLineRaw, "key") Or $CmdLineRaw == "" Then
    ConsoleWrite("Advanced Encryption Standard Tool - ALBANESE Research Lab " & Chr(184) & " 2016-2023" & @CRLF) ;
    ConsoleWrite("Usage: " & @ScriptName & " -e|d --in <file.ext> --out <output.ext> --key <key>" & @CRLF & @CRLF) ;
    ConsoleWrite("Commands: " & @CRLF) ;
    ConsoleWrite("   -e: Encrypt " & @CRLF) ;
    ConsoleWrite("   -d: Decrypt" & @CRLF & @CRLF) ;
    ConsoleWrite("Parameters: " & @CRLF) ;
    ConsoleWrite("   /in : Input file" & @CRLF) ;
    ConsoleWrite("   /out: Output file (Optional [*])" & @CRLF) ;
    ConsoleWrite("   /key: 128-bit key" & @CRLF & @CRLF) ;
    ConsoleWrite("   [*] If no output is specified, the input file will be overwritten." & @CRLF) ;
    Exit
Else
    Local $file = _CmdLine_Get('in')
    Local $outfile = _CmdLine_Get('out')
    Local $key = _CmdLine_Get('key')
EndIf

If _CmdLine_KeyExists('out') Then
    Local $outfile = _CmdLine_Get('out')
Else
    Local $outfile = $file
EndIf

If FileExists($file) Then
    If $CmdLine[0] > 1 And $CmdLine[1] == "-e" Or $CmdLine[1] == "-d" Then
        $full = FileRead($file)
        If $CmdLine[1] == "-e" Then
            _Crypt_Startup()
            $key = _Crypt_ImportKey($CALG_AES_128, $key)
            _Crypt_SetKeyParam($key, $KP_MODE, $CRYPT_MODE_CBC)
            FileOpen($outfile, 2)
            FileWrite($outfile, StringEncrypt(True, $full, $key))
        ElseIf $CmdLine[1] == "-d" Then
            _Crypt_Startup()
            $key = _Crypt_ImportKey($CALG_AES_128, $psw)
            _Crypt_SetKeyParam($key, $KP_MODE, $CRYPT_MODE_CBC)
            FileOpen($outfile, 2)
            FileWrite($outfile, StringEncrypt(False, $full, $key))
        EndIf
    EndIf
Else
    ConsoleWrite("Error: """ & $file & """ not found." & @CRLF)  ;
EndIf

Func StringEncrypt($bEncrypt, $sData, $sPassword)
    _Crypt_Startup() ; Start the Crypt library.
    Local $vReturn = ''
    If $bEncrypt Then ; If the flag is set to True then encrypt, otherwise decrypt.
        $vReturn = _Crypt_EncryptData($sData, $sPassword, $CALG_USERKEY)
    Else
        $vReturn = _Crypt_DecryptData($sData, $sPassword, $CALG_USERKEY)
    EndIf
    _Crypt_Shutdown() ; Shutdown the Crypt library.
    Return $vReturn
EndFunc   ;==>StringEncrypt

Func _Crypt_ImportKey($iALG_ID, $sKey)
    Local Const $PLAINTEXTKEYBLOB = 0x8  ;The key is a session key.
    Local Const $CUR_BLOB_VERSION = 2

    Local $bKey = Binary($sKey), $iKeyLen = BinaryLen($bKey)

    Local $tagPUBLICKEYBLOB = "struct; BYTE bType; BYTE bVersion; WORD reserved; dword aiKeyAlg; dword keysize; byte key[" & $iKeyLen & "]; endstruct;"

    Local $tBLOB = DllStructCreate($tagPUBLICKEYBLOB)
    DllStructSetData($tBLOB, "bType", $PLAINTEXTKEYBLOB)
    DllStructSetData($tBLOB, "bVersion", $CUR_BLOB_VERSION)
    DllStructSetData($tBLOB, "aiKeyAlg", $iALG_ID)
    DllStructSetData($tBLOB, "keysize", $iKeyLen)
    DllStructSetData($tBLOB, "key", Binary($bKey))

    Local $aRet = DllCall(__Crypt_DllHandle(), "bool", "CryptImportKey", "handle", __Crypt_Context(), "ptr", DllStructGetPtr($tBLOB), "dword", DllStructGetSize($tBLOB), "ptr", 0, "dword", 0, "ptr*", 0)
    If @error Then Return SetError(2, @error)

    Return SetError(Not $aRet[0], 0, $aRet[6])
EndFunc   ;==>_Crypt_ImportKey

Func _Crypt_SetKeyParam($hKey, $iParam, $vData, $iFlags = 0, $sDataType = Default)
    If Not $sDataType Or $sDataType = Default Then $sDataType = "ptr"

    Local $aRet = DllCall(__Crypt_DllHandle(), "bool", "CryptSetKeyParam", "handle", $hKey, "dword", $iParam, $sDataType, $vData, "dword", $iFlags)
    If @error Then Return SetError(2, @error)

    Return SetError(Not $aRet[0], 0, $aRet[0])
EndFunc   ;==>_Crypt_SetKeyParam

Compatible w/ FireFox's* PHP code:
 

<?php
$block=mcrypt_get_block_size('rijndael-128', 'cbc');

$key='abcdefghijuklmno';
$str='hello world!';

//zero to PKCS7 padding
$pad=$block-(strlen($str)%$block);
$str.=str_repeat(chr($pad), $pad);

$s=mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str,  MCRYPT_MODE_CBC);

echo 'Encrypted: '.base64_encode($s);
?>

Also with OpenSSL-PHP:

Result Decrypted:
<?php
    $pass = 'abcdefghijuklmno';
    $method = 'aes-128-cbc';
    $iv = "0000000000000000";

    print (openssl_decrypt("iisRzInRXH0GNGzCtDPeHg==", $method, $pass, false, $iv));
?>
<BR>
Result Encrypted:
<?php
    $pass = 'abcdefghijuklmno';
    $method = 'aes-128-cbc';
    $iv = "0000000000000000";

    print (openssl_encrypt("SECRET MESSAGE", $method, $pass, false, $iv));
?>

So decrypt:

$ openssl enc -d -aes-128-cbc -K 6162636465666768696a756b6c6d6e6f -iv 00 < output.ext

Thanks for the tips, but I intend to write just a program in pure Autoit that is compatible with PHP and OpenSSL;

I hope it can be useful for someone.

 

 

 

SecurityKit_AutoIt-OpenSSL.zip

Edited by Radix
It's CBC!
Posted

I'm writing a platform for non-Techies to interact with. I wrote the administrative programs in Golang and I need GUIs for common users who won't understand what the initialization vector is all about. It is for arbitrators and mediators in an arbitration chamber to exchange messages securely without really understanding cryptography. My madness.

AutoIt Rules! Respect!

  • Moderators
Posted

Moved to the appropriate AutoIt General Help and Support forum, as the Developer General Discussion forum very clearly states:

Quote

General development and scripting discussions.


Do not create AutoIt-related topics here, use the AutoIt General Help and Support or AutoIt Technical Discussion forums.

Moderation Team

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Posted (edited)

I feel a little unsure about recommending the use of this tool. I am reluctant as it just* supports OpenSSL but is not cryptographically secure these days.

The OpenSSL enc command by itself is not the best option when needing to symmetrically encrypt some file. The enc Command is not secure and no cryptographer recommends it as it is outdated. Encryption in CBC/ECB or even CTR mode, are useless without an authentication step with asymmetric or symmetric signature (HMAC), because the ciphertext can be trivially tampered with and hashed recalculated and, when decrypting, no one will understand or even notice that there is something wrong with the plaintext as these modes are unauthenticated encrypted text.

That's why today there are AEAD modes (Authenticated Encryption w/ Associated Data), which is the secure way to use symmetric cryptography nowadays. Well, back to AES-ECB/CBC, even more insecure than the CBC mode, is the ECB not only for not using the initialization vector, but for encrypting each block individually. This makes the Tux image a distorted image if it feels large scale. However, the CBC would also be of no use if used without IV. Both are unsafe and should be used with caution.

With that in mind, and assuming that one of the two must be used, either CBC or ECB, it is necessary to take a series of precautions to avoid surprises, that is, if the user of this program is unaware of this information, it is better not to use these codes .

But if, as a last resort, it is necessary to use it, it is good to keep in mind that:

For repetitive texts, it's better to use CBC (no PHP and OpenSSL compatibility), or use RC4. RC4 is a very good cipher, but it has been widely misused, as in the case of WEP, where the same password was used over and over again to encrypt sequentials of identical length, which jeopardizes the security of RC4. It is good to emphasize that RC4 is considered unsafe, but because it has been misused. Likewise, the ECB has restrictions that prevent its use today, assuming that human error is also a software vulnerability.

Well, duly aware, it is necessary:

 1-) Do not use the same password for two different messages
 2-) Do not use two different passwords for the same message
 3-) Authenticate the ciphertext at least with HMAC

I'm striving for compatibility and interoperability of my own tools based on OpenSSL reference which is legacy and cross platform, and I'm only going to deal with non-secret sensitive information, but like I said that's crazy. I myself wrote a tool that supplants OpenSSL and doesn't suffer from buffer* overflows and supportsAEAD modes: https://github.com/pedroalbanese/edgetk

In short, if you have to deal with sensitive but not secret data, you can use these techniques. But if you are going to deal with large amounts and undertakings and possibility of adversaries and malicious intent, it is better not to use OpenSSL nor Autoit for this. (I mean, the AutoIt part is perfect, the problem is in the native Windows API in terms of encryption./cryptographically.)


I mean, I intend to publish these tools but it will contain this foreshadowing..

Edited by Radix
spellcheck
Posted (edited)

Today, after 5 minutes of testing, I noticed that the tools worked all the time in CBC mode, to my surprise. The PHP codes worked because the Autoit code permformed CBC-encryption with null IV, which means it is decryptable by ECB mode (only the first 16-bytes for AES). As I had only tested strings shorter than 16, I didn't realize this.

This is quite positive, that is, forget what I said about ECB and keep the three rules:
  1-) Do not use the same password for two different messages
  2-) Do not use two different passwords for the same message
  3-) Authenticate the ciphertext at least with HMAC

SecurityKit_AutoIt-OpenSSL contains:

  1-) Hash tools, including a recursive hasher

  2-) HMAC tools

  3-) Bulk encryption tools (suports AES128-CBC, RC4-40 and RC4-128)

Any tips are welcome.

SecurityKit_AutoIt-OpenSSL.zip

Edited by Radix
  • 2 weeks later...
Posted (edited)

I didn't understand. In 2017 this script worked with key derivation, today I am using the same structure and algorithms for the same application which now works without key derivation in 2023. I don't see why reset semantic versioning or copyright. Ah, OK. I can't do this because it's possible that I die in 2025 and someone who has the script on an old machine in 2032 and runs the script will think I'm alive and providing support..

As for the size of the keys, this tool is not suitable for inserting random keys so to speak, it is meant to be used with IKM, i.e. a Diffie-Hellman shared key derived in some way like HKDF or PBKDF and, in the absence of these , HMAC.

It is imperative that the user knows the length of the keys and that he has a mechanism to generate appropriate keys for using this script in conjunction with other tools in other languages. I mean, whoever is programming a cryptographic system in PHP will not find problems in generating keys and will need mechanisms for this.

The keys used are ephemeral, meaning they cannot be reused, there is no point in memorizing a 128-bit key as they should not be reused in this tool. That is, if it is the case of using memorized or invented keys on the fly, it is best to use the AutoIt3 example tool which performs the same tasks and supports passowrds of any length. Otherwise, you will need a tool to generate the keys in the correct size so that this step does not depend on manual verification (knowing the length of each key that will be used), as this system should be automatic.

Edited by Radix
  • 7 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...