Как экспортировать ключ Web Crypto в jsrsasign

Я пытаюсь сгенерировать ключ RSA с помощью Web Crypto и использовать его для подписи строки с помощью jsrsasign (Firefox делает не поддерживает RSA-PSS). Поэтому я экспортирую ключ Web Crypto и преобразовываю его в PKCS8-PEM, но когда я вызываю KEYUTIL.getKeyFromPlainPrivatePKCS8PEM для импорта ключа в jsrsasign, возникает ошибка: деформированный простой закрытый ключ PKCS8 (код: 001)

Что я сделал не так? JSBin

window.crypto.subtle.generateKey(
  {
    name: "RSA-OAEP",
    modulusLength: 2048,
    publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
    hash: {name: "SHA-256"},
  },
  true,
  ["encrypt", "decrypt"]
)
.then(keyPair => window.crypto.subtle.exportKey("pkcs8", keyPair.privateKey))
.then(arrayBufferToBase64String)
.then(toPem)
.then(pem => {
  var rsa = KEYUTIL.getKeyFromPlainPrivatePKCS8PEM(pem); // throws: malformed plain PKCS8 private key(code:001)
  var sig = rsa.signStringPSS('text', 'sha256', 32);
  console.log('signature', sig);
})
.catch(::console.error)

function arrayBufferToString(arrayBuffer) {
  var byteArray = new Uint8Array(arrayBuffer)
  var byteString = '';
  for (var i=0; i<byteArray.byteLength; i++) {
    byteString += String.fromCharCode(byteArray[i]);
  }
  return byteString;
}

function arrayBufferToBase64String(arrayBuffer) {
  return btoa(arrayBufferToString(arrayBuffer));
}

function toPem(key) {
  return `
-----BEGIN RSA PRIVATE KEY-----
${key}
-----END RSA PRIVATE KEY-----
`;
}

Редактировать:

Я только что понял, что jsrsasign может обрабатывать jwk:

window.crypto.subtle.generateKey(
  {
    name: "RSA-OAEP",
    modulusLength: 2048,
    publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
    hash: {name: "SHA-256"},
  },
  true,
  ["encrypt", "decrypt"]
)
.then(keyPair => window.crypto.subtle.exportKey("jwk", keyPair.privateKey))
.then(jwk => {
  var rsa = KEYUTIL.getKey(jwk);
  var sig = rsa.signStringPSS('text', 'sha256', 32);
  console.log('signature', sig);
})
.catch(::console.error)

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


person maiermic    schedule 16.11.2015    source источник


Ответы (2)


Ваш закодированный ключ PEM на самом деле является PKCS # 1, а не PKCS # 8 из-за части «RSA». Это просто объект ключа RSA в DER без идентификатора ключа, заключенного в последовательность.

jsrsasign ищет заголовок PKCS#8 «BEGIN PRIVATE KEY», а не «BEGIN RSA PRIVATE KEY». Изменение заголовка заставляет его работать.

person felix    schedule 21.11.2015

Это не работает, если изменить заголовок PEM с "----BEGIN RSA PRIVATE KEY-----" на "-----BEGIN PRIVATE KEY-----", поскольку содержимое отличается. Я думаю, что использование JWK для экспорта файлов — лучший способ сделать это, поскольку он будет иметь большую совместимость с любым браузером. Я пробовал то же самое раньше, однако PKCS#8 не работает в некоторых браузерах.

Как описал Феликс, ваш ключ RSA — это ключ PKCS#1 с заголовком "-----BEGIN RSA PRIVATE KEY-----" PEM.

Если вам нужно преобразовать PKCS#1 в PKCS#8, ключевой класс KEYUTIL может быть полезен, как в этом примере:

keyobj = KEYUTIL.getKey("-----BEGIN RSA PRIVATE KEY-----..."); // your key
pkcs8pem = KEYUTIL.getPEM(keyobj, "PKCS8PRV");
person kjur    schedule 25.09.2016