C # DES против Java DES Byte [] и BlockSize отличается - PullRequest
1 голос
/ 28 июня 2019

Я пытаюсь заставить код Java выводить тот же байт [], что и код C #.

Код C #:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class Program
{
    private const string k = "A2B3C4D1";
    private const string kiv = "1A2B3C4D";

    public static void Main()
    {
        encrypt("peanuts");
    }

    public static void encrypt(string str)
    {
        try
        {
            using (var ms = new MemoryStream())
            using (var csp = new DESCryptoServiceProvider() { Key = Encoding.UTF8.GetBytes(k), IV =  Encoding.UTF8.GetBytes(kiv) })
            {
                Console.WriteLine("Algorithm: DES?/" + csp.Mode + "/" + csp.Padding);
                Console.WriteLine("BlockSize: " + csp.BlockSize);

                using (var cs = new CryptoStream(ms, csp.CreateEncryptor(), CryptoStreamMode.Write))
                using (var sw = new StreamWriter(cs))
                    sw.WriteLine(str);

                byte[] barray = ms.ToArray();

                Console.WriteLine("barray length: " + barray.Length);

                Console.WriteLine("barray: " + string.Join(" ", barray));
            }
        }
        catch (Exception ex) { Console.Write(ex.ToString()); }
    }
}

Код Java:

import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class MyClass {
    private static final String k = "A2B3C4D1";
    private static final String kiv = "1A2B3C4D";

    public static void main(String args[]) {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

        encrypt("peanuts");
    }

    public static void encrypt(String str) {
        try {
            SecretKeySpec key = new SecretKeySpec(k.getBytes(Charset.forName("UTF-8")), "DES");
            IvParameterSpec iv = new IvParameterSpec(kiv.getBytes(Charset.forName("UTF-8")));
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS7Padding");
            cipher.init(Cipher.ENCRYPT_MODE, key, iv);

            System.out.println("Algorithm: " + cipher.getAlgorithm());
            System.out.println("BlockSize: " + cipher.getBlockSize());

            ByteArrayOutputStream out = new ByteArrayOutputStream();
            CipherOutputStream cos = new CipherOutputStream(out, cipher);

            cos.write(str.getBytes());
            cos.close();

            byte[] barray = out.toByteArray();

            System.out.println("barray length: " + barray.length);

            System.out.print("barray: ");
            for(byte b : barray){
                System.out.print(" " + b);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

C # Выход

Алгоритм: DES? / CBC / PKCS7

BlockSize: 64

длина поля: 16

barray: 107 125 91 205 77 206 98 120 214 194 64 167 128 97 132 75

base64: a31bzU3OYnjWwkCngGGESw ==

Java Output

Алгоритм: DES / CBC / PKCS7Padding

Размер блока: 8

длина полосы: 8

длина поля: 45 100 -86 103 9 -7-19 -76

base64: LWSqZwn57bQ =

Я пытаюсь получить точно такой же Byte[] вывод из кода Java, как я уже получаю из C#,Но единственное отличие, которое мне удалось увидеть, это то, что размер блока отличается от обоих.

C # Dot.Net Fiddle

Java jDoodle.com

Я просто не понимаю, есть что-то, чего мне не хватает или я не понимаю?

EDIT

Я добавил код для распечатки массива байтов встрока, она отличается:

C #

barray length: 16
barray: 107 125 91 205 77 206 98 120 214 194 64 167 128 97 132 75
base64: a31bzU3OYnjWwkCngGGESw==

Java

barray length: 8
barray: 45 100 -86 103 9 -7 -19 -76
base64: LWSqZwn57bQ=

1 Ответ

2 голосов
/ 28 июня 2019

@ JamesKPolk правильно: вы шифруете { (byte)'p', (byte)'e', (byte)'a', (byte)'n', (byte)'u', (byte)'t', (byte)'s', (byte)'\r', (byte)'\n' } в C # и { (byte)'p', (byte)'e', (byte)'a', (byte)'n', (byte)'u', (byte)'t', (byte)'s' } в Java.

Поскольку "арахис" составляет (в UTF-8) 7 байтов, он может быть дополнен PKCS7 в один блок DES. Следующие 1-8 байтов приводят ко второму блоку ... и вы добавили два.

Изменение кода в скрипте Dot.Net на Write вместо WriteLine приводит к

Algorithm: DES?/CBC/PKCS7
BlockSize: 64
barray length: 8
barray: 45 100 170 103 9 249 237 180
barray: LWSqZwn57bQ=

, где теперь единственное отличие состоит в том, что C # BlockSize - это биты, а в вашем Java-коде он представлен в байтах.

Измените "peanuts" на "peanuts\r\n" в вашем JDoodle, и вы получите

Algorithm: DES/CBC/PKCS7Padding
BlockSize: 8
barray length: 16
barray:  107 125 91 -51 77 -50 98 120 -42 -62 64 -89 -128 97 -124 75
barray: a31bzU3OYnjWwkCngGGESw==

То же самое, если десятичное содержимое barray было напечатано в виде значений без знака вместо значений со знаком (добавьте 256 ко всем отрицательным числам) - факт, легко видимый в Base64, является тем же.

...