Appearance
Entschlüsseln von Daten
1. Codebeispiel C#
csharp
using System.Collections.Generic;
using System.Text;
using System;
using System.Security.Cryptography;
using System.IO;
namespace CuraGo.Internal
{
public static class Crypt
{
static readonly Encoding Ansi;
static Crypt() => Ansi = Encoding.GetEncoding("Windows-1252");
public static string Decrypt(string key, string data)
{
switch (GetCryptVersionFromString(data))
{
case 1:
return DecryptAnsi(key, data);
case 2:
return DecryptUtf8Aes256(key, data);
}
Console.WriteLine($"Fehler bei Entschlüsselung. Ungültige Eingabe: {data}");
return "";
}
static bool InputTextToEncryptIsValid(int expectedVersion, string encryptedData, out byte[] initVector, out byte[] cipherText, out string errorText)
{
initVector = null;
cipherText = null;
var cryptChunks = encryptedData.Split(new char[]{'$'},StringSplitOptions.RemoveEmptyEntries);
if (cryptChunks.Length == 3)
{
if (int.TryParse(cryptChunks[0], out var actualVersion))
{
if (actualVersion == expectedVersion)
{
var base64InitVector = cryptChunks[1];
if (base64InitVector.Length > 0)
{
var base64CipherText = cryptChunks[2];
initVector = Convert.FromBase64String(base64InitVector);
cipherText = Convert.FromBase64String(base64CipherText);
errorText = "";
return true;
}
else
{
errorText = $"Fehler bei Entschlüsselung. Kein Initialisierungsvektor angegeben.";
return false;
}
}
else
{
errorText = $"Fehler bei Entschlüsselung. Erwartete Version: '{expectedVersion}' Erhaltene Version: '{actualVersion}'";
return false;
}
}
else
{
errorText = $"Fehler bei Entschlüsselung. Ungültige Version: '{cryptChunks[0]}'";
return false;
}
}
else
{
errorText = $"Fehler bei Entschlüsselung. Ungültige Eingabe: '{encryptedData}'";
return false;
}
}
static string DecryptUtf8Aes256(string key, string encryptedData)
{
const int expectedVersion = 2;
if (InputTextToEncryptIsValid(expectedVersion,encryptedData,out var initVector,out var cipherText, out var errorText))
{
try
{
var sha256Key = new SHA256Managed().ComputeHash(Encoding.UTF8.GetBytes(key));
using (var aesManaged = new AesManaged())
{
aesManaged.Key = sha256Key;
aesManaged.IV = initVector;
aesManaged.Padding = PaddingMode.PKCS7;
aesManaged.Mode = CipherMode.CBC;
// Create a decrytor to perform the stream transform.
var decryptor = aesManaged.CreateDecryptor(aesManaged.Key, aesManaged.IV);
// Create the streams used for decryption.
using (var memoryStreamDecrypt = new MemoryStream(cipherText))
{
using (var cryptoStreamDecrypt = new System.Security.Cryptography.CryptoStream(memoryStreamDecrypt, decryptor, System.Security.Cryptography.CryptoStreamMode.Read))
{
using (var streamReaderDecrypt = new StreamReader(cryptoStreamDecrypt,Encoding.UTF8))
{
var decryptedData = streamReaderDecrypt.ReadToEnd();
return decryptedData;
}
}
}
}
}
catch (Exception e)
{
Console.WriteLine($"Fehler bei Entschlüsselung. {e.Message}");
return "";
}
}
Console.WriteLine($"Fehler bei Entschlüsselung. {errorText}");
return "";
}
static int GetCryptVersionFromString(string inputString)
{
if (inputString.Length >= 3)
{
var versionString = inputString.Substring(0, 3);
if (versionString[0] == '$')
{
char[] versionChars = { versionString[1], versionString[2] };
var strVersion = new string(versionChars);
if (int.TryParse(strVersion, out var cryptVersion))
return cryptVersion;
}
}
return 1;
}
static byte[] ReadAllBytes(Stream stream)
{
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
return ms.ToArray();
}
}
static string DecryptAnsi(string key, string data)
{
if (string.IsNullOrEmpty(data))
return "";
try
{
byte[] sha256Key = new SHA256Managed().ComputeHash(Ansi.GetBytes(key));
byte[] initVector = new MD5CryptoServiceProvider().ComputeHash(Ansi.GetBytes(key));
byte[] encryptedData = Convert.FromBase64String(data);
List<byte> toDecryptData = new List<byte>();
toDecryptData.AddRange(encryptedData);
using (var aesManaged = new AesManaged())
{
aesManaged.Key = sha256Key;
aesManaged.IV = initVector;
aesManaged.Padding = PaddingMode.None;
aesManaged.Mode = CipherMode.CBC;
// Create a decrytor to perform the stream transform.
var decryptor = aesManaged.CreateDecryptor(aesManaged.Key, aesManaged.IV);
// Create the streams used for decryption.
using (var memoryStreamDecrypt = new MemoryStream(toDecryptData.ToArray()))
{
using (var cryptoStreamDecrypt = new CryptoStream(memoryStreamDecrypt, decryptor, CryptoStreamMode.Read))
{
var decryptedData = ReadAllBytes(cryptoStreamDecrypt);
int padSize = decryptedData[0];
byte[] result = new byte[decryptedData.Length - padSize - 1];
Array.ConstrainedCopy(decryptedData, 1, result, 0, result.Length);
return Ansi.GetString(result, 0, result.Length);
}
}
}
}
catch (Exception e)
{
Console.WriteLine($"Fehler bei Entschlüsselung. {e.Message}");
return "Fehler bei Entschlüsselung";
}
}
}
}2. Codebeispiel Go
go
package curasoft
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"crypto/sha256"
"encoding/base64"
"errors"
"log"
"strings"
)
func Decrypt(key, cyphertext string) (string, error) {
version := getCryptVersion(cyphertext)
switch version {
case 1:
return decryptVersionOne(cyphertext, key)
case 2:
return decryptVersionTwo(cyphertext, key)
}
return "", nil
}
func getCryptVersion(cypherText string) int {
stringSlice := strings.Split(cypherText, "$")
if len(stringSlice) >= 4 {
versionString := stringSlice[1]
if versionString == "02" {
return 2
}
}
return 1
}
// version 1
func decryptVersionOne(data string, passphrase string) (string, error) {
if data == "" {
return "", nil
}
rawData, err := base64.StdEncoding.DecodeString(data)
if err != nil {
log.Print(err)
return "", err
}
key := createSHA256Hash(passphrase)
iv := createMD5Hash(passphrase)
block, err := aes.NewCipher(key)
if err != nil {
log.Printf("cipher err %s", err)
return "", err
}
decrypted := make([]byte, len(rawData))
cipher.NewCBCDecrypter(block, iv).CryptBlocks(decrypted, rawData)
padSize := decrypted[0]
text := decrypted[1:(len(decrypted) - int(padSize))]
return string(text), nil
}
// version 2
func decryptVersionTwo(data, passphrase string) (string, error) {
key := createSHA256Hash(passphrase)
stringSlice := strings.Split(data, "$")
iv, err := base64.StdEncoding.DecodeString(stringSlice[2])
if err != nil {
return "", err
}
rawData, err := base64.StdEncoding.DecodeString(stringSlice[3])
if err != nil {
return "", err
}
block, err := aes.NewCipher(key)
if err != nil {
log.Printf("cipher err %s", err)
}
decrypted := make([]byte, len(rawData))
cipher.NewCBCDecrypter(block, iv).CryptBlocks(decrypted, rawData)
unPadded, err := pkcs7strip(decrypted, block.BlockSize())
if err != nil {
return "", err
}
return string(unPadded), nil
}
func pkcs7strip(data []byte, blockSize int) ([]byte, error) {
length := len(data)
if length == 0 {
return nil, errors.New("pkcs7: Data is empty")
}
if length%blockSize != 0 {
return nil, errors.New("pkcs7: Data is not block-aligned")
}
padLen := int(data[length-1])
ref := bytes.Repeat([]byte{byte(padLen)}, padLen)
if padLen > blockSize || padLen == 0 || !bytes.HasSuffix(data, ref) {
return nil, errors.New("pkcs7: Invalid padding")
}
return data[:length-padLen], nil
}
func createSHA256Hash(key string) []byte {
hasher := sha256.New()
hasher.Write([]byte(key))
return hasher.Sum(nil)
}
func createMD5Hash(key string) []byte {
hasher := md5.New()
hasher.Write([]byte(key))
return hasher.Sum(nil)
}3. Codebeispiel PHP
php
<?php
namespace Curasoft;
class Crypt
{
/**
* @param string $key
* @param string $data
* @return string
*/
public static function Decrypt(string $key, string $data): string
{
switch (static::GetCryptVersionFromString($data))
{
case 1:
return static::DecryptInternalOld($key, $data);
case 2:
return static::DecryptUtf8Aes256($key, $data);
}
return "";
}
/**
* @param string $key
* @param string $data
* @return string
*/
static function DecryptUtf8Aes256(string $key, string $data): string
{
if (strlen($data) > 3)
{
$version = '02';
// Trennt nach $ auf und entfernt leere Elemente
$splittedData = array_values(array_filter(explode("$", $data), 'strlen'));
if (count($splittedData) == 3 && $splittedData[0] == $version)
{
$sha256key = hash('sha256', $key, true);
$cryptMethod = "AES-256-CBC";
$initVector = base64_decode($splittedData[1]);
$cipherData = base64_decode($splittedData[2]);
// Wenn kein Padding angegeben, wird automatisch PKCS#7 genommen
return openssl_decrypt($cipherData, $cryptMethod, $sha256key, OPENSSL_RAW_DATA, $initVector);
}
}
return "";
}
/**
* @param string $data
* @return int
*/
static function GetCryptVersionFromString(string $data): int
{
if (strlen($data) >= 3)
{
$versionString = substr($data, 0, 3);
if ($versionString[0] == '$') {
$versionString = $versionString[1] . $versionString[2];
if (is_numeric($versionString))
{
return intval($versionString);
}
}
}
return 1;
}
/**
* @param string $key
* @param string $data
* @return string
*
* Alte-Version:
* Mitarbeiter-Namen von CuraSoft-Seite aus könnten Ansi-Bytes enthalten, deswegen wird am Ende ein utf8_encode durchgeführt,
* um diese auf der Seite sauber darzustellen.
* Alles andere (Passwörter, DataKeys) enthalten nur ASCII-Zeichen. Deswegen ist auch an dieser Stelle ein utf8_encode ungefährlich.
*/
static function DecryptInternalOld(string $key, string $data): string
{
// Schlüssel und Initialisierungsvektor vorbereiten
$hashed_key = hash('sha256', $key, true);
$init_vector = md5($key, true);
// Base64 Input
$decoded_data = base64_decode($data);
// Entschlüsseln
$decrypted = openssl_decrypt(
$decoded_data,
'aes-256-cbc',
$hashed_key,
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,
$init_vector
);
// Das erste Byte auslassen und den Inhalt ohne ZeroBytes rausholen
$data = substr($decrypted, 1, strlen($decrypted) - ord(substr($decrypted, 0, 1)) - 1);
return utf8_encode($data);
}
}