Расшифруйте строку base64, используя закрытый ключ RSA в nodeJS

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

Строка была зашифрована с использованием алгоритма Java RSA с преобразованием RSA/ECB/OAEPWithSHA-1AndMGF1Padding.

Мне удалось добраться до следующего кода:

import forge from "node-forge";

function decryptWithPrivateKey(encryptedBase64String: string, privateKeyString: string) {
  try {

    // Remove spaces and newlines from the privateKeyString
    privateKeyString = privateKeyString.replace(/\s/g, '');

    console.info('encryptedBase64String: ' + encryptedBase64String);
    console.info('privateKeyString: ' + privateKeyString);

    const privateKey = forge.pki.privateKeyFromPem(privateKeyString);
    
    const encryptedBuffer = Buffer.from(encryptedBase64String, 'base64');
    const encryptedBytes = forge.util.createBuffer(encryptedBuffer.toString('binary'));

    const decryptedBytes = privateKey.decrypt(encryptedBytes.bytes(), 'RSA-OAEP', {
        md: forge.md.sha1.create(),
        mgf1: {
            md: forge.md.sha1.create()
        }
    });

    return decryptedBytes.toString();
  } catch (error: any) {
    console.info(error.message);
    //throw new Error('Error: ' + error.message);
  }
}

const decryptedString = decryptWithPrivateKey(encryptedPassword, privateKey);
console.info(decryptedString);

Но все, что я получаю, это ошибка: Invalid PEM formatted message.

Я уверен, что мой закрытый ключ верен и моя строка сгенерирована правильно. Я прекрасно могу использовать его на Java.

Что не так с моим кодом?

Моя строка для декодирования: FfKZ2sKQO6sCndb4orGYVIPGBNNsh/eWHu8Ay4MOFfess3B7IBaxBIqq6CUbmgwCbl2D0I38h7OEIO4VI1aC0lH4wMESzxPF5N6724e1SAXPEi0f/F3SA8sMy+mApZtWoUUwmeMPmDap7JII0DxuOngWwiRzwBK7KXc1ww2JLv9aPisBeTWme6QxAMgBpHREQJ9ymxVxRdxa3OyiwsrtgUDORp+z8+cvSLBQwEnjc228YJ0P1n/ggX1O6U/ytzogtVjVniw+TbSHNnZhcjHzPHs6sjYTOZFx3yoYfbh08hiUk3l7jRDXeGYNEgiBUAWY/zhn97VEgcuEYS9TQIEePw==

И мой закрытый ключ следующий: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDNZQq9bWwqyFKnheZOhGabLpPDWKbJeIz6YoJNDF8VlzjVnPIgr5ft5iEanvEl7qYBojq1GKzwa7vTxrLt6AHZXCB7ITfhGp4iMtVVtA+vJgBurSKkPBhVoRpewv1YbAsdEKMZ2wkopHEEuRVi5ngUEV6klccuqGiYZHapzbrw06Wpx7+dmMkB56RuWm18kKx9sMclEBk84LyGuVvkR8W86axy3MWTBPq1wHw8YDG77vBFKgOTdwfp+QsYDoZ+Eph0s9RB6Re1kyX97nXthaLJPi44knnA02VmwwDEGjX7cli2TllRwhs9SOdBheA8iNltU7erXGo9MkSLJwu3Xae5AgMBAAECggEBAKMV2KpCKQHrX52+tvifLm2HVTJlwMD2JFJnR3jwGsuk8C7E2IhVhHgUIzLlAysQS+W+L4k914tqr4/fFJHMhzNUcEH0RU9KeEdFP5k2SMHUlcFLXdc0FEphifO2Nb0wxL5GSIsuHR6VO1v5rd6CitO8Wv6qIqaMd8iQ9JutTAMNTjNG/FWCLkjkWBdtulUOrprlNAmJ4KTKG2ZXVMdjuYFq7++w5Bhouo038jZIDfCksan4CNUAccg03cW9OKl3Vkw6jPCBKWxk/fZChzReb3kot1YQEq8+DDlSTT8xEss9FuF6caX6PRFHgNaeHOq3Eza616dgS87uJbZ8uycbU8UCgYEA5ylrb3GVVALsqI3i+yLF+SaKCxTXwZfpbZes9sUiCaDI0GP3EsJAolrBcA3/io08FTUXpqxLEH7VojJa7oPKTSmo75T5amjp3Xx4NbweFVN4R4oxfR9tgJGnnGCOF2EaLVr3ofWMQK5ObU4VqMXbaKe0dX6vvKrYAHETPuBHlBcCgYEA43bYYICjNN51ez7rHe/RsqYbRbgj8eT504OgOQdkqWAcHEe5YQu1k6bAGXfC9bmVw8ZxITLoQmjJ2ph1lJbw/1UD6VvToXwdC0U/sf4+ICdrA7Al3BS74D2caQBBAy9AL5My7PtECCBBcNCPDMg9PDPLtbv6JAiyugfkdLdzdK8CgYAy1mQfTT6HDGGZrCKoEnyxj606RKoylEMs6/eJCc+ziF3Bnsp+oKPwUL9L8ngps2fsThHWgPu9M/etxR9EZ019bNUPY5b6tPoB0NbrEmUXUZUZPqYlm1zMsrvG42E8eQl1whTF1Ke0reDnnw2aYXEgcgl48ZSajIQWjMerw01anwKBgCsag0hOOB81pKeVNbK3llI3PeXJTi5xiJH3WG5WI1IhX1JQmSV1tZPkPnTVCAHOiD3QJfH3lqG2/8FHsMhWjhakgpg/CWyJe2t+VOKi3hzzu0i4oYQB/dQxeKlBHhC/bHdXeogD2VF840nAi8sNSuVUn16x32XirBOqmTUw6lULAoGBAK41Wu99ZlLRpqRuWTSqyuF2H46Vq3fa0spm4OsULMMZZgVYVev11sFtakQUp4AUw/QsgnEjtZdzg05dUZDDOBsYvyUVYUi1AMGDYI3Zw8UsmzqqH9dNjweO1zAGgVAvh1/HIgi8pwpIyaDOPx9NJnXhOO+pUU3C0z1kSBo9uiLM

Ваш ключ представляет собой закрытый ключ RSA в кодировке ASN.1/DER в кодировке Base64 (в формате PKCS#8), а для privateKeyFromPem() требуется ключ в кодировке PEM.

Topaco 07.05.2024 21:27

Хорошо, а как мне изменить свой код, чтобы я мог правильно его декодировать?

Vinicius Garcia 07.05.2024 21:30

Для кодирования ключа PEM вставьте разрыв строки после каждых 64 символов и добавьте заголовок PKCS#8 (-----BEGIN PRIVATE KEY-----) и нижний колонтитул (-----END PRIVATE KEY-----), например здесь.

Topaco 07.05.2024 21:31

Или base64-декодируйте то, что есть и пользуйтесь privateKeyFromAsn1().

President James K. Polk 07.05.2024 21:38
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
191
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Как отметил @Topaco, мой ключ представляет собой закрытый ключ RSA с кодировкой Base64 в кодировке ASN.1/DER (в формате PKCS#8), и я не хочу его менять.

@President Джейм К. Полк предлагает использовать privateKeyFromAsn1(), поэтому я меняю свой код на следующий:

function decryptWithPrivateKey(encryptedBase64String: string, privateKeyBase64String: string) {
  try {

    // Remove spaces and newlines from the privateKeyBase64
    privateKeyBase64String = privateKeyBase64String.replace(/\s/g, '');

    console.info('encryptedBase64String: ' + encryptedBase64String);
    console.info('privateKeyBase64String: ' + privateKeyBase64String);

    // Decode Base64 encoded private key to binary
    const privateKeyBinary = forge.util.decode64(privateKeyBase64String);
    
    // Importing the DER encoded key directly
    const privateKey = forge.pki.privateKeyFromAsn1(forge.asn1.fromDer(privateKeyBinary));
    
    const encryptedBuffer = Buffer.from(encryptedBase64String, 'base64');
    const encryptedBytes = forge.util.createBuffer(encryptedBuffer.toString('binary'));

    const decryptedBytes = privateKey.decrypt(encryptedBytes.bytes(), 'RSA-OAEP', {
        md: forge.md.sha1.create(),
        mgf1: {
            md: forge.md.sha1.create()
        }
    });

    return decryptedBytes.toString();
  } catch (error: any) {
    console.info(error.message);
    //throw new Error('Error: ' + error.message);
  }
}

Это помогло решить мою проблему!

Ps: Отредактировано для прямого импорта ключа, закодированного в DER, как сказал @Topaco в комментарии.

Нет необходимости преобразовывать ключ, закодированный DER, в ключ, закодированный PEM. Вы можете напрямую импортировать ключ в кодировке DER: const privateKeyBinary = forge.util.decode64(privateKeyBase64String); const privateKey = forge.pki.privateKeyFromAsn1(forge.asn1.fromDer(privateKeyBi‌​nary)), s. вот . Альтернативно, ключ в кодировке PEM можно импортировать напрямую с помощью privateKeyFromPem().

Topaco 07.05.2024 22:00

Спасибо за совет, отредактировано, чтобы добавить его в решение. Мой код теперь работает отлично

Vinicius Garcia 07.05.2024 22:09

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