Расшифровка байтового массива RSA/ECB/NoPadding в Golang

У меня есть код Java, в который я отправляю пакет с зашифрованным ключом:

protected void write()
{
    writeC(0x00);
    writeD(_sessionId);
    writeD(PROTOCOL_VERSION);
    writeB(_publicKey); --- > scrambled key
    writeB(UNKNOWN_GG);
    writeB(_blowfishKey);
    writeC(0x00);
}

В моем Java-коде я могу правильно расшифровать зашифрованный ключ, используя следующий метод расшифровки:

public void run()
{
    final LoginClient client = getClient();
    
    byte[] decrypted = null;
    try
    {
        final Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
        rsaCipher.init(Cipher.DECRYPT_MODE, client.getRSAPrivateKey());
        decrypted = rsaCipher.doFinal(_raw, 0x00, 0x80);
    }
    catch (GeneralSecurityException e)
    {
        LOGGER.error("Failed to generate a cipher.", e);
        client.close(LoginFail.REASON_ACCESS_FAILED);
        return;
    }
    
    try
    {
        final String user = new String(decrypted, 0x5E, 14).trim().toLowerCase();
        final String password = new String(decrypted, 0x6C, 16).trim();

        LoginController.getInstance().retrieveAccountInfo(client, user, password);
    }
    catch (Exception e)
    {
        LOGGER.error("Failed to decrypt user/password.", e);
        client.close(LoginFail.REASON_ACCESS_FAILED);
    }
}

В Java расшифровка работает правильно со следующими входными данными:

Зашифрованный ключ:

[124, 168, 24, 242, 228, 213, 212, 54, 235, 100, 160, 114, 163, 61, 75, 218, 182, 245, 166, 34, 214, 132, 15, 71, 135, 194, 141, 227, 38, 1, 217, 145, 203, 135, 209, 137, 111, 33, 54, 34, 57, 0, 189, 243, 199, 219, 109, 56, 15, 225, 143, 59, 176, 108, 76, 204, 232, 133, 216, 126, 70, 30, 115, 74, 25, 0, 133, 38, 128, 16, 28, 183, 155, 24, 188, 86, 117, 191, 135, 36, 211, 165, 104, 217, 6, 182, 164, 136, 101, 215, 42, 113, 111, 55, 208, 207, 105, 35, 182, 47, 241, 107, 139, 215, 213, 249, 43, 125, 219, 34, 53, 103, 250, 92, 154, 128, 75, 189, 168, 128, 229, 6, 239, 177, 101, 126, 218, 75]

Закрытый ключ Java:

SunRsaSign RSA private CRT key, 1024 bits
  params: null
  modulus: 91851415039980683673835443907833548355613725060429787547716446884026400945844827342368025805543719063805785824109075005634172820422680533076648130137521254244221874431195148950936257983839718841574094615493929797376689026996944801887459231860502077721291214210394902757594184173778070286729141127782416296193
  private exponent: 6487635995240407475566233880851450254636860602479965310563184653343274943593934811905055029279061836006484620592961353145255138101173202734513392349460393317252650745961877082056763589015732603463063131507792018004450541681668317154023863374611531824451608552071840032997073721859882730955156029598795586149
Chave privada (formato Go):
&rsa.PrivateKey{
  PublicKey: rsa.PublicKey{
    N: big.NewInt(0).SetBytes(new byte[] {0, -126, -52, -2, 101, -128, 16, 28, -73, -101, 24, -68, 86, 117, 15, -21, 104, 31, -91, 104, -39, 6, -74, -92, -120, 101, -41, 42, 113, 111, 55, -48, -49, 105, 35, -74, 47, -15, 107, -117, -41, -43, -7, 43, 125, -37, 34, 53, 103, -6, 92, -102, -128, 75, -67, -88, -128, -27, 6, -17, -79, 101, 126, -38, 75, 101, -88, -99, -44, 100, -59, -56, -127, 112, 124, 28, 36, -42, 25, 0, -123, 38, 80, -50, -5, -48, 50, -85, -49, -30, 21, -89, -110, 73, 54, 9, 94, -94, -92, 103, -90, -98, 74, -67, -11, -20, -7, -106, -114, 28, -7, 88, 95, -11, -67, 21, -69, -5, -47, -28, 76, 13, -125, 55, -49, 35, 96, -87, 1, }),
    E: 65537,
  },
  D: big.NewInt(0).SetBytes(new byte[] {9, 61, 27, 118, -27, -35, -67, 121, -122, 125, -17, -57, -105, -117, 33, 80, -128, 115, -71, 125, 34, -55, 65, -61, -44, -107, -89, 12, -50, 19, 62, 47, 120, 56, -86, -124, -90, 99, -73, 67, -18, 124, 36, 3, 70, -72, 26, -41, -106, 74, 118, 43, 59, -82, 80, -71, -111, -13, -76, 120, 110, 55, -48, -119, 74, -39, 58, 44, -63, -103, -73, -80, 57, 1, 64, -60, -33, -53, -21, 53, -45, -7, -42, 113, 60, 12, 38, 24, -66, 9, -111, 18, -108, -38, 30, 114, -77, -83, -9, 34, 88, -44, -114, -79, -54, -17, 44, 2, -36, -117, -74, 122, -62, -103, 14, 115, -39, 18, 73, -69, -77, -62, -111, -127, -102, -12, 90, 101, }),
}

Массив байтов для расшифровки:

[89, 250, 193, 103, 219, 4, 129, 208, 181, 30, 127, 250, 147, 113, 64, 25, 187, 96, 88, 15, 64, 93, 100, 141, 42, 89, 13, 157, 253, 187, 118, 154, 150, 132, 238, 224, 22, 98, 35, 252, 92, 253, 138, 6, 38, 142, 170, 247, 136, 19, 231, 48, 52, 228, 22, 222, 81, 242, 182, 109, 96, 209, 7, 187, 213, 237, 218, 147, 238, 28, 25, 217, 81, 200, 219, 76, 214, 232, 238, 193, 78, 252, 180, 45, 182, 150, 220, 157, 194, 11, 57, 195, 20, 174, 13, 123, 69, 72, 81, 112, 49, 143, 3, 67, 216, 86, 11, 234, 48, 210, 254, 136, 201, 238, 1, 222, 134, 178, 102, 230, 102, 137, 145, 236, 197, 2, 120, 106]

Однако когда я пытаюсь воспроизвести процесс расшифровки в Golang с помощью пакета crypto/rsa, я сталкиваюсь с проблемами. Реализация Go выглядит так:

func NewScrambledKeyPairTest(bits int) (ScrambledKeyPair, error) {
    scrambledModulusJava := []byte{124, 168, 24, 242, 228, 213, 212, 54, 235, 100, 160, 114, 163, 61, 75, 218, 182, 245, 166, 34, 214, 132, 15, 71, 135, 194, 141, 227, 38, 1, 217, 145, 203, 135, 209, 137, 111, 33, 54, 34, 57, 0, 189, 243, 199, 219, 109, 56, 15, 225, 143, 59, 176, 108, 76, 204, 232, 133, 216, 126, 70, 30, 115, 74, 25, 0, 133, 38, 128, 16, 28, 183, 155, 24, 188, 86, 117, 191, 135, 36, 211, 165, 104, 217, 6, 182, 164, 136, 101, 215, 42, 113, 111, 55, 208, 207, 105, 35, 182, 47, 241, 107, 139, 215, 213, 249, 43, 125, 219, 34, 53, 103, 250, 92, 154, 128, 75, 189, 168, 128, 229, 6, 239, 177, 101, 126, 218, 75}
    privateKey := &rsa.PrivateKey{
        PublicKey: rsa.PublicKey{
            N: big.NewInt(0).SetBytes([]byte{
                0, 130, 204, 254, 101, 128, 16, 28, 185, 155, 24, 188, 86, 117, 15, 235, 104, 31, 165, 104, 217, 6, 182, 164, 136, 101, 215, 42, 113, 111, 55, 208, 207, 105, 35, 182, 47, 241, 107, 139, 215, 213, 249, 43, 125, 219, 34, 53, 103, 250, 92, 154, 128, 75, 189, 168, 128, 229, 6, 239, 177, 101, 126, 218, 75, 101, 168, 157, 212, 100, 197, 200, 129, 112, 124, 28, 36, 214, 25, 0, 133, 38, 80, 206, 251, 208, 50, 171, 207, 226, 21, 169, 146, 73, 54, 9, 94, 162, 164, 103, 166, 158, 74, 189, 245, 236, 249, 150, 142, 28, 249, 88, 95, 245, 189, 21, 187, 251, 209, 228, 76, 13, 131, 55, 207, 35, 96, 169, 1,
            }),
            E: 65537,
        },
        D: big.NewInt(0).SetBytes([]byte{
            9, 61, 27, 118, 229, 221, 189, 121, 134, 125, 239, 199, 151, 139, 33, 80, 128, 115, 185, 125, 34, 201, 65, 195, 212, 149, 167, 12, 206, 19, 62, 47, 120, 56, 170, 132, 166, 99, 185, 67, 238, 124, 36, 3, 70, 184, 26, 215, 150, 74, 118, 43, 59, 174, 80, 185, 145, 243, 180, 120, 110, 55, 208, 137, 74, 217, 58, 44, 193, 153, 183, 176, 57, 1, 64, 196, 223, 203, 235, 53, 211, 249, 214, 113, 60, 12, 38, 24, 190, 9, 145, 18, 148, 218, 30, 114, 179, 173, 247, 34, 88, 212, 142, 177, 202, 239, 44, 2, 220, 139, 182, 122, 194, 153, 14, 115, 217, 18, 73, 187, 179, 194, 145, 129, 154, 244, 90, 101,
        }),
    }

    return ScrambledKeyPair{
        Pair:             privateKey,
        ScrambledModulus: scrambledModulusJava,
    }, nil
}


func (p RequestLogin) Run(client *clients.Client, rand io.Reader) error {
    privateKey := client.PrivateKey()

    c := new(big.Int).SetBytes(p.raw)
    m := new(big.Int)
    m.Exp(c, privateKey.D, privateKey.N)
    em := m.Bytes()

    user := string(em[0x5E : 0x5E+14])
    pwd := string(em[0x6C : 0x6C+16])

    return nil
}

Но мне не удалось расшифровать эти байты:

[89, 250, 193, 103, 219, 4, 129, 208, 181, 30, 127, 250, 147, 113, 64, 25, 187, 96, 88, 15, 64, 93, 100, 141, 42, 89, 13, 157, 253, 187, 118, 154, 150, 132, 238, 224, 22, 98, 35, 252, 92, 253, 138, 6, 38, 142, 170, 247, 136, 19, 231, 48, 52, 228, 22, 222, 81, 242, 182, 109, 96, 209, 7, 187, 213, 237, 218, 147, 238, 28, 25, 217, 81, 200, 219, 76, 214, 232, 238, 193, 78, 252, 180, 45, 182, 150, 220, 157, 194, 11, 57, 195, 20, 174, 13, 123, 69, 72, 81, 112, 49, 143, 3, 67, 216, 86, 11, 234, 48, 210, 254, 136, 201, 238, 1, 222, 134, 178, 102, 230, 102, 137, 145, 236, 197, 2, 120, 106]

значение этих байтов после расшифровки в Java таково:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 97, 100, 109, 105, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 100, 109, 105, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Но в Golang я не могу, потому что в Java я использую: Cipher.getInstance("RSA/ECB/nopadding"); e В Golang я не нашел функции для расшифровки фрагмента байта без заполнения.

Не опасно ли использовать RSA без заполнения gg? Конечно, вы это знаете :) crypto.stackexchange.com/questions/1448/… вы пробовали использовать rsa.DecryptPKCS1v15, но он с заполнением, поэтому вам нужно вручную удалить заполнение после расшифровки. По возможности используйте прокладку, более безопасную и лучшую совместимость.

Christoph 14.08.2024 09:13

Что значит...Но у меня не получается расшифровать...? Неправильный результат (опубликовать результат), исключение (опубликовать трассировку исключения/стека)...? В чем разница между зашифрованным ключом ([124, 168,...) и массивом байтов для расшифровки ([89, 250,...)?

Topaco 14.08.2024 09:28
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш код не является исполняемым напрямую, и вы не описываете точно, в чем проблема (неправильный результат, исключение...). Когда я запускаю расшифровку (модульное возведение в степень) ваших данных:

ciphertextBytes := ([]byte{89, 250, 193, 103, 219, 4, 129, 208, 181, 30, 127, 250, 147, 113, 64, 25, 187, 96, 88, 15, 64, 93, 100, 141, 42, 89, 13, 157, 253, 187, 118, 154, 150, 132, 238, 224, 22, 98, 35, 252, 92, 253, 138, 6, 38, 142, 170, 247, 136, 19, 231, 48, 52, 228, 22, 222, 81, 242, 182, 109, 96, 209, 7, 187, 213, 237, 218, 147, 238, 28, 25, 217, 81, 200, 219, 76, 214, 232, 238, 193, 78, 252, 180, 45, 182, 150, 220, 157, 194, 11, 57, 195, 20, 174, 13, 123, 69, 72, 81, 112, 49, 143, 3, 67, 216, 86, 11, 234, 48, 210, 254, 136, 201, 238, 1, 222, 134, 178, 102, 230, 102, 137, 145, 236, 197, 2, 120, 106})[0:128]
modulusInt := "91851415039980683673835443907833548355613725060429787547716446884026400945844827342368025805543719063805785824109075005634172820422680533076648130137521254244221874431195148950936257983839718841574094615493929797376689026996944801887459231860502077721291214210394902757594184173778070286729141127782416296193"
privateExpInt := "6487635995240407475566233880851450254636860602479965310563184653343274943593934811905055029279061836006484620592961353145255138101173202734513392349460393317252650745961877082056763589015732603463063131507792018004450541681668317154023863374611531824451608552071840032997073721859882730955156029598795586149"

c := new(big.Int)
c.SetBytes(ciphertextBytes)
n := new(big.Int)
n.SetString(modulusInt, 10)
d := new(big.Int)
d.SetString(privateExpInt, 10)

decrypted := new(big.Int).Exp(c, d, n).Bytes()
fmt.Println(hex.EncodeToString(decrypted)) // 24000061646d696e00000000000000000061646d696e000000000000000000000000000000

Я получаю правильный результат (в шестнадцатеричном кодировании):

24000061646d696e00000000000000000061646d696e000000000000000000000000000000

Единственное отличие от результата кода Java состоит в том, что код Java автоматически дополняет результат спереди значениями 0x00 до размера/модуля ключа, тогда как при прямом модульном возведении в степень этого, конечно, не происходит.

Чтобы это исправить, вы можете просто дополнить себя, чтобы индексы были правильными, например:

decryptedPadded := append(make([]byte, 128-len(decrypted)), decrypted...)
fmt.Println(hex.EncodeToString(decryptedPadded[0x5E : 0x5E+14])) // 61646d696e000000000000000000
fmt.Println(string(decryptedPadded[0x5E : 0x5E+14])) // admin

Безопасность. Как уже упоминалось в комментарии, шифрование RSA без заполнения небезопасно. Кроме того, в настоящее время следует использовать ключ размером не менее 2048 бит (256 байт).


Обновлено: код, указанный в вашем комментарии, использует неправильные массивы байтов для модуля и частного показателя. Правильные значения можно вывести следующим образом, например: для модуля:

modulusInt := "91851415039980683673835443907833548355613725060429787547716446884026400945844827342368025805543719063805785824109075005634172820422680533076648130137521254244221874431195148950936257983839718841574094615493929797376689026996944801887459231860502077721291214210394902757594184173778070286729141127782416296193"
n := new(big.Int)
n.SetString(modulusInt, 10)
fmt.Println(n.Bytes()) // [130 204 254 101 128 16 28 183 155 24 188 86 117 15 235 104 31 165 104 217 6 182 164 136 101 215 42 113 111 55 208 207 105 35 182 47 241 107 139 215 213 249 43 125 219 34 53 103 250 92 154 128 75 189 168 128 229 6 239 177 101 126 218 75 101 168 157 212 100 197 200 129 112 124 28 36 214 25 0 133 38 80 206 251 208 50 171 207 226 21 167 146 73 54 9 94 162 164 103 166 158 74 189 245 236 249 150 142 28 249 88 95 245 189 21 187 251 209 228 76 13 131 55 207 35 96 169 1]

То же самое и с частным экспонентом. При сравнении со своими значениями вы обнаружите отклонения в несколько байт.

Это приводит к следующему для закрытого ключа:

privateKey := &rsa.PrivateKey{
    PublicKey: rsa.PublicKey{
        N: big.NewInt(0).SetBytes([]byte{130, 204, 254, 101, 128, 16, 28, 183, 155, 24, 188, 86, 117, 15, 235, 104, 31, 165, 104, 217, 6, 182, 164, 136, 101, 215, 42, 113, 111, 55, 208, 207, 105, 35, 182, 47, 241, 107, 139, 215, 213, 249, 43, 125, 219, 34, 53, 103, 250, 92, 154, 128, 75, 189, 168, 128, 229, 6, 239, 177, 101, 126, 218, 75, 101, 168, 157, 212, 100, 197, 200, 129, 112, 124, 28, 36, 214, 25, 0, 133, 38, 80, 206, 251, 208, 50, 171, 207, 226, 21, 167, 146, 73, 54, 9, 94, 162, 164, 103, 166, 158, 74, 189, 245, 236, 249, 150, 142, 28, 249, 88, 95, 245, 189, 21, 187, 251, 209, 228, 76, 13, 131, 55, 207, 35, 96, 169, 1}),
        E: 65537,
    },
    D: big.NewInt(0).SetBytes([]byte{9, 61, 27, 118, 229, 221, 189, 121, 134, 125, 239, 199, 151, 139, 33, 80, 128, 115, 185, 125, 34, 201, 65, 195, 212, 149, 167, 12, 206, 19, 62, 47, 120, 56, 170, 132, 166, 99, 183, 67, 238, 124, 36, 3, 70, 184, 26, 215, 150, 74, 118, 43, 59, 174, 80, 185, 145, 243, 180, 120, 110, 55, 208, 137, 74, 217, 58, 44, 193, 153, 183, 176, 57, 1, 64, 196, 223, 203, 235, 53, 211, 249, 214, 113, 60, 12, 38, 24, 190, 9, 145, 18, 148, 218, 30, 114, 179, 173, 247, 34, 88, 212, 142, 177, 202, 239, 44, 2, 220, 139, 182, 122, 194, 153, 14, 115, 217, 18, 73, 187, 179, 194, 145, 129, 154, 244, 90, 101}),
}

При этом расшифровка работает.

Простите меня за отрицательный голос, это был промах, я жду момента, чтобы проголосовать за, извините !!

Ming 14.08.2024 17:12

может мне помочь здесь: go.dev/play/p/b7DyQpweidd? я использую закрытый ключ и безуспешно:/

Ming 14.08.2024 17:19

если я использую rsa.PrivateKey, не работает:/

Ming 14.08.2024 17:49

@Ming - Ваши массивы байтов для модуля и частной экспоненты неверны, см. раздел редактирования в моем ответе и для иллюстрации go.dev/play/p/oZC0pdJ8tt_u и go.dev/play/p/9fZ8te4JX9g

Topaco 14.08.2024 20:06

Другие вопросы по теме

Похожие вопросы

Пользовательский элемент управления JavaFX не отображает параметр «При действии»
Как интерполировать цвет узла с помощью пользовательских переменных CSS?
Try — catch не может перехватить исключение, потому что, когда исключение произошло, введите рекурсию в catch, блок try не работает и просто попадает в блок catch
Каковы распространенные методы поиска второго по величине элемента массива и какова временная сложность каждого метода?
Откуда мы можем получить com.sun.mail?
Как заставить этот метод всегда возвращать неотрицательное значение?
Значение слов «in» и «out» в дженериках Kotlin
Попытка перехватить исключения при преобразовании массива строк в целые числа
Столкновение с NullPointerException при попытке внедрить репозиторий в приложение весенней загрузки
Почему этот пример сложения чисел с плавающей запятой в Java ведет себя так, как будто мантисса имеет длину 24 бита?