Попытка сгенерировать подпись RSA с помощью Python из рабочего кода С#

Я использую чужой код для создания подписи RSA, используемой для проверки в файлах сохранения Xbox 360. Код считывает необходимые значения из файлов и корректно генерирует подпись.

Код:

    byte[] xHash=null;
    RSAParameters xParams = new RSAParameters();
    br.BaseStream.Position = 0x1A8;
    xParams.D = br.ReadBytes(0x80);
    xParams.Exponent = br.ReadBytes(0x4);
    xParams.Modulus = br.ReadBytes(0x80);
    xParams.P = br.ReadBytes(0x40);
    xParams.Q = br.ReadBytes(0x40);
    xParams.DP = br.ReadBytes(0x40);
    xParams.DQ = br.ReadBytes(0x40);
    xParams.InverseQ = br.ReadBytes(0x40);
    br.close();

    br=new BinaryReader(File.OpenRead(f));
    br.BaseStream.Position=0x22c;
    xHash = new SHA1CryptoServiceProvider().ComputeHash(br.ReadBytes(0x118));
    byte[] xrsa=SignatureGenerate(xParams, xHash);

public static byte[] SignatureGenerate(RSAParameters xParam, byte[] xHash)
        {
            RSACryptoServiceProvider xRSACrypto = new RSACryptoServiceProvider();
            RSAPKCS1SignatureFormatter xRSASigFormat = new RSAPKCS1SignatureFormatter();
            xRSACrypto.ImportParameters(xParam);
            xRSASigFormat.SetHashAlgorithm("SHA1");
            xRSASigFormat.SetKey(xRSACrypto);
            return xRSASigFormat.CreateSignature(xHash);

        }

Я пытаюсь закончить с тем, что есть в xrsa, но используя Python. Я установил pycrypto и просматриваю документацию, но мне все еще не хватает чего-то очевидного. Во-первых, RSA.construct из Crypto.PublicKey принимает только шесть параметров, но не показатели степени один и два (DP и DQ). Кроме того, входные данные должны быть длинными. В коде C# значения имели длину 128 и 64 байта, а не 4 байта.

Я знаю, что это может показаться до боли очевидным, но я понятия не имею, что мне нужно делать.

Я работаю с Python 2.7.3

edit: также «сообщение», которое нужно зашифровать, представляет собой хэш sha1 размером 0x118 байт файла, который содержит метаданные и хэш других частей файла.

edit: Большое спасибо, мата, я чувствую, что ближе к тому, чтобы заставить его работать. Он по-прежнему не соответствует подписи С#. В C# формат подписи устанавливается как SHA1. Что это делает и можно ли это сделать в Python?


person mowwwalker    schedule 26.04.2012    source источник


Ответы (2)


хорошо, во-первых: long в python не 4 байта. в python у long нет предопределенного размера, поэтому использование long для хранения 128-байтового числа не проблема. чтобы преобразовать байтовую строку в длинную, вы можете использовать:

long_value = long(string_value.decode('hex'), 16)
# maybe someone knows a better way?

не может быть, чтобы файл был в форме DER? в этом случае вы просто можете просто прочитать файл, используя:

from Crypto.PublicKey import RSA
with open("keyfile", "rb") as f:
    key = RSA.importKey(f.read())

если нет, вероятно, было бы лучше преобразовать его в PEM или DER, чтобы вам не приходилось самостоятельно читать параметры. в любом случае, последние три параметра в RSA. конструкция необязательна, специально u можно вычислить как 1/p % q (where p > q). по крайней мере, из того, что я пробовал, это работает, даже если вы укажете только первые три параметра.

person mata    schedule 26.04.2012
comment
Большое спасибо, я нашел инструмент Java для преобразования ключа xml в rem, и я успешно подписываю строку в Python! Однако он все еще не соответствует строке С#. В C# код также устанавливает алгоритм хеширования SHA1 — я обновлю оп. Есть ли способ сделать это с помощью pycrypto? - person mowwwalker; 27.04.2012
comment
Вы должны использовать Crypto.Signature.PKCS1_v1_5 - person SquareRootOfTwentyThree; 27.04.2012
comment
@SquareRootOfTwentyThree, хорошо, я чувствую, что приближаюсь, но это все еще не соответствует сигнатуре C#. Строка, которую я получаю с возвратом sign(), что это за база? - person mowwwalker; 27.04.2012
comment
sign() возвращает строку байтов. Подпись PKCS1 рандомизирована, поэтому маловероятно, что вы получите один и тот же результат дважды (независимо от того, какой язык вы используете). - person SquareRootOfTwentyThree; 27.04.2012
comment
@SquareRootOfTwentyThree, я каждый раз получаю один и тот же результат с C#. Есть ли способ заставить его давать тот же результат, что и на С#? - person mowwwalker; 27.04.2012
comment
@SquareRootOfTwentyThree, есть ли способ предотвратить рандомизацию? - person mowwwalker; 27.04.2012
comment
Извините, я ввел вас в заблуждение. Теперь я вижу, что PKCS1 PSS рандомизирован. но PKCS1 v1.5 (очевидно, тот, который используется RSAPKCS1SignatureFormatter) - нет. - person SquareRootOfTwentyThree; 27.04.2012
comment
@SquareRootOfTwentyThree, я подумал, что это может быть так, поэтому я также попробовал PKCS1 PSS и все равно каждый раз получал разные результаты. Кроме того, вы имеете в виду, что наоборот? - person mowwwalker; 27.04.2012

Я попробовал pycrypto и другую библиотеку, но получил только то, что хотел, работая с M2Crypto.

Установка M2Crypto в Windows была серьезной проблемой, но с установочным файлом здесь все было очень просто:

http://chandlerproject.org/bin/view/Projects/MeTooCrypto

Ссылка для загрузки установщика Windows находится здесь: http://chandlerproject.org/pub/Projects/MeTooCrypto/M2Crypto-0.21.1.win32-py2.7.exe

person mowwwalker    schedule 27.04.2012