AES и SHA256 Шифрование/описание между C# и Ruby [закрыто]C#

Место общения программистов C#
Ответить
Anonymous
 AES и SHA256 Шифрование/описание между C# и Ruby [закрыто]

Сообщение Anonymous »

Процесс шифрования и дешифрования в моем коде не соответствует процессу банка. Другими словами, когда я использую свой код для шифрования и расшифровки, все работает нормально. Но когда я пытаюсь отправить результат шифрования моего кода в банк, они отвечают, что они не могут расшифровать его, потому что процессы шифрования не совпадают.{
"isOk": false,
"message": "Error: Padding is invalid and cannot be removed.",
"body": null
}
< /code>
В идеальном сценарии мой код Ruby шифрует информацию, а затем их система получает зашифрованный JSON, расшифровывает данные и реагирует, повторно замахивая информацию. Теперь моя система расшифрует информацию после получения ответа.using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Text;

var textEncrypted = Encrypt(json, LoadCertificateBusiness());

Console.WriteLine("Encrypted Data:");
Console.WriteLine(textEncrypted);

static string Encrypt(string plainText, X509Certificate2 certificate)
{
var bytesToEncrypted = Encoding.UTF8.GetBytes(plainText);
var publicKeyBytes = certificate.GetPublicKey();
var passwordBytes = SHA256.Create().ComputeHash(publicKeyBytes);
var bytesEncrypted = EncryptAES(bytesToEncrypted, passwordBytes);
return Convert.ToBase64String(bytesEncrypted);
}

static string Decrypt(string encryptedText, X509Certificate2 certificate)
{
if (encryptedText == null!)
{
return null!;
}

var bytesToBeDecrypted = Convert.FromBase64String(encryptedText);
var key = certificate.GetPublicKey();
var passwordBytes = SHA256.Create().ComputeHash(key);
var bytesDecrypted = DecryptAES(bytesToBeDecrypted, passwordBytes);
return Encoding.UTF8.GetString(bytesDecrypted);
}

static byte[] EncryptAES(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null!;
var saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

using (MemoryStream ms = new MemoryStream())
{
using (Aes AES = Aes.Create())
{
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;

using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}

return encryptedBytes;
}

static byte[] DecryptAES(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null!;
var saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

using (MemoryStream ms = new MemoryStream())
{
using (Aes AES = Aes.Create())
{
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;

using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}

return decryptedBytes;
}

X509Certificate2 LoadCertificateBusiness()
{
string certificateThumbPrint = ""; // BUSINESS certificate thumbprint
var x509CertificatesStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
x509CertificatesStore.Open(OpenFlags.ReadOnly);

var certCollection = x509CertificatesStore.Certificates.Find(
X509FindType.FindByThumbprint,
certificateThumbPrint,
false
);

X509Certificate2 certPublic = certCollection.OfType().FirstOrDefault()!;
x509CertificatesStore.Close();

return certPublic;
}
< /code>
мой код до сих пор < /p>
require 'openssl'
require 'base64'
require 'json'
require 'digest'

class SecurityManagerV2
SALT_BYTES = [1, 2, 3, 4, 5, 6, 7, 8].pack('C*').freeze
PBKDF2_ITERATIONS = 1000
AES_KEY_SIZE = 32 # 256 bits / 8
AES_IV_SIZE = 16 # 128 bits / 8

BUSINESS_CER_PATH = Rails.root.join('config', 'certificates', 'example.cer').to_s.freeze

# Encrypt plaintext using certificate's public key with AES
def self.encrypt(plain_text, certificate)
bytes_to_encrypted = plain_text.encode('UTF-8')
public_key_bytes = certificate.public_key.to_der
password_bytes = Digest::SHA256.digest(public_key_bytes)
bytes_encrypted = encrypt_aes(bytes_to_encrypted, password_bytes)
Base64.strict_encode64(bytes_encrypted)
end

# Decrypt encrypted text using certificate's public key
def self.decrypt(encrypted_text, certificate)
return nil if encrypted_text.nil?

bytes_to_be_decrypted = Base64.strict_decode64(encrypted_text)
key = certificate.public_key.to_der
password_bytes = Digest::SHA256.digest(key)
bytes_decrypted = decrypt_aes(bytes_to_be_decrypted, password_bytes)
bytes_decrypted.force_encoding('UTF-8')
end

# AES encryption using PBKDF2 key derivation
def self.encrypt_aes(bytes_to_be_encrypted, password_bytes)
# Derive key and IV using PBKDF2 (equivalent to Rfc2898DeriveBytes)
key_iv = OpenSSL::PKCS5.pbkdf2_hmac(
password_bytes,
SALT_BYTES,
PBKDF2_ITERATIONS,
AES_KEY_SIZE + AES_IV_SIZE,
OpenSSL::Digest.new('SHA1')
)

key = key_iv[0, AES_KEY_SIZE]
iv = key_iv[AES_KEY_SIZE, AES_IV_SIZE]

# Create AES cipher
cipher = OpenSSL::Cipher.new('AES-256-CBC')
cipher.encrypt
cipher.key = key
cipher.iv = iv

# Encrypt data
cipher.update(bytes_to_be_encrypted) + cipher.final
end

# AES decryption using PBKDF2 key derivation
def self.decrypt_aes(bytes_to_be_decrypted, password_bytes)
# Derive key and IV using PBKDF2 (equivalent to Rfc2898DeriveBytes)
key_iv = OpenSSL::PKCS5.pbkdf2_hmac(
password_bytes,
SALT_BYTES,
PBKDF2_ITERATIONS,
AES_KEY_SIZE + AES_IV_SIZE,
OpenSSL::Digest.new('SHA1')
)

key = key_iv[0, AES_KEY_SIZE]
iv = key_iv[AES_KEY_SIZE, AES_IV_SIZE]

# Create AES decipher
decipher = OpenSSL::Cipher.new('AES-256-CBC')
decipher.decrypt
decipher.key = key
decipher.iv = iv

# Decrypt data
decipher.update(bytes_to_be_decrypted) + decipher.final
end

# Load business certificate (for encryption/decryption)
def self.load_certificate_business
load_certificate_from_cer(BUSINESS_CER_PATH)
end

# Load certificate from CER file (X.509 format, public key only)
def self.load_certificate_from_cer(cer_path)
# File existence validation
unless File.exist?(cer_path)
error_msg = "CER file not found: #{cer_path}"
raise error_msg
end

# File readability validation
unless File.readable?(cer_path)
error_msg = "CER file is not readable: #{cer_path}"
raise error_msg
end

file_size = File.size(cer_path)

if file_size.zero?
error_msg = "CER file is empty: #{cer_path}"
raise error_msg
end

cer_data = File.read(cer_path)

# Load X.509 certificate (DER format expected)
certificate = OpenSSL::X509::Certificate.new(cer_data)
CertificateWithKey.new(certificate, nil)
rescue OpenSSL::X509::CertificateError => e
error_msg = "Failed to load CER certificate: #{e.message}. File may not be a valid X.509 certificate in DER format"
raise error_msg
rescue StandardError => e
error_msg = "Unexpected error loading CER certificate: #{e.message}"
raise error_msg
end

# Helper class to hold certificate and private key together
class CertificateWithKey
attr_reader :certificate, :private_key

def initialize(certificate, private_key)
@certificate = certificate
@private_key = private_key
puts "[DEBUG] CertificateWithKey initialized with #{private_key ? 'private key' : 'public key only'}"
end

def public_key
@certificate.public_key
end

def to_der
@certificate.to_der
end

def to_pem
@certificate.to_pem
end
end
end
< /code>
Что мне не хватает? Мое шифрование предоставляет ряд размера 3180, а банк содержит 2880.{
"companyId": 2295,
"password": "pato123AB",
"documentNumber": "4850147",
"documentType": "Q",
"documentExtension": "LP",
"documentComplement": " ",
"amount": 5196.33,
"currency": "BOL",
"fundSource": "PRUEBA",
"fundDestination": "PRUEBA",
"sourceAccount": "2011040905323",
"sourceCurrency": "BOL",
"description": "PRUEBA",
"sendVouchers": "prueba@gmail.com",
"cismartApprovers": [
{
"idc": "00255921-Q-LP 1A",
"type": 1
}
],
"spreadsheet": {
"formAchPayments": [
{
"paymentType": "ACH",
"line": 1,
"accountNumber": "4027922806",
"titularName": "TUMOMO SRL",
"firstLastName": "TUMOMO SRL",
"secondLastName": " ",
"amount": 388,
"branchOfficeId": 201,
"firstDetail": "Detalle 1",
"mail": "",
"bankId": "1003",
"documentNumber": "123456789",
"documentType": "Q",
"documentExtension": "LP",
"documentComplement": ""
},
{
"paymentType": "ACH",
"line": 2,
"accountNumber": "4027922806",
"titularName": "TU SHOP ALANIS DANIELA MENDOZA",
"firstLastName": "TU SHOP ALANIS DANIELA MENDOZA",
"secondLastName": " ",
"amount": 2699.93,
"branchOfficeId": 201,
"firstDetail": "Detalle 1",
"mail": "",
"bankId": "1003",
"documentNumber": "123456789",
"documentType": "Q",
"documentExtension": "LP",
"documentComplement": ""
},
{
"paymentType": "ACH",
"line": 3,
"accountNumber": "4027922806",
"titularName": "LOS TIEMPOS - EDITORIAL CANELA",
"firstLastName": "LOS TIEMPOS - EDITORIAL CANELA",
"secondLastName": " ",
"amount": 2108.4,
"branchOfficeId": 201,
"firstDetail": "Detalle 1",
"mail": "",
"bankId": "1003",
"documentNumber": "123456789",
"documentType": "Q",
"documentExtension": "LP",
"documentComplement": ""
}
]
}
}
< /code>
Сертификат < /p>
json_data = JSON.parse(json_content).to_s.to_json
encrypted = SecurityManagerV2.encrypt(json_data, load_certificate_business)
puts encrypted # result to compare
< /code>
После обработки JSON, который я поделился через код C#, он производит этот базовый 64, который я не могу воспроизвести.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


Подробнее здесь: https://stackoverflow.com/questions/797 ... p-and-ruby
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»