Web Crypto API: RSA 개인 키로 해독
17710 단어 암호화공개키WebCryptoAPI보안
소개
브라우저측은 RSA의 공개열쇠키로 암호화해, 서버측(Node.js)은 프라이빗 키로 복호를 시도하면, 이하의 에러가 발생해, webcrypto 모듈을 사용해 해소할 수 있었습니다.
Error: error:04099079:rsa routines:RSA_padding_check_PKCS1_OAEP_mgf1:oaep decoding error
at Object.privateDecrypt (internal/crypto/cipher.js:53:12)
Web Crypto API란?
사양 요약 페이지 : htps : //로 ゔぇぺぺr. 모잖아. 오 rg / 그럼 / cs / u b / ap / u b_Cryp 및 _ Api
페이지에 있는 경고에 따라 신중하게 대응해야 합니다.
출처 : htps : //로 ゔぇぺぺr. 모잖아. 오 rg / 그럼 / cs / u b / ap / u b_Cryp 및 _ Api
Web Crypto API 주요 메소드
Window.crypto 또는 crypto 객체에서 SubtleCrypto라는 인터페이스에서 여러 메서드를 확인할 수 있습니다.
SubtleCrypto
사양 요약 페이지 : htps : //로 ゔぇぺぺr. 모잖아. 오 rg / 그럼 / cs / u b / ap / u b_Cryp 및 _ Api
페이지에 있는 경고에 따라 신중하게 대응해야 합니다.
출처 : htps : //로 ゔぇぺぺr. 모잖아. 오 rg / 그럼 / cs / u b / ap / u b_Cryp 및 _ Api
Web Crypto API 주요 메소드
Window.crypto 또는 crypto 객체에서 SubtleCrypto라는 인터페이스에서 여러 메서드를 확인할 수 있습니다.
SubtleCrypto
의사 난수 생성: Crypto.getRandomValues
대칭 암호화의 IV 생성에 필요한 의사 난수 생성 메소드도 자주 사용하는 메소드입니다.
typedArray = cryptoObj.getRandomValues(typedArray);
사용 예:
var array = new Uint32Array(10);
window.crypto.getRandomValues(array);
결과:
지원되는 알고리즘
출처 : htps : //로 ゔぇぺぺr. 모잖아. 오 rg / Enu S / Docs / Ue b / Api / Su bt Cryp
브라우저측: 공개키로 암호화
공개키로 암호화에는 공개키의 임포트와 암호화의 2개의 수속이 있습니다.
・공개키의 임포트:SubtleCrypto.importKey()
const result = crypto.subtle.importKey(
format, // raw(AESの鍵),pkcs8(RSAのプライベート鍵),spki(SubjectPublicKeyInfo:RSAまたはElliptic Curveの公開鍵),jwk(JSON Web Key)
keyData, // キーデータ。ArrayBuffer、TypedArray、JSONWebKeyオブジェクト
algorithm, // ①、RsaHashedImportParams :RSA-OAEP、RSA-PSS。②、EcKeyImportParams:ECDSA、ECDH。③、HmacImportParams :HMAC ④、{ "name": ALGORITHM }:AES-CTR, AES-CBC, AES-GCM、AES-KW。 ⑤、PBKDF2
extractable, // true/false。 SubtleCrypto.exportKey() or SubtleCrypto.wrapKey()メソッドを使うか
usages // ["encrypt", "decrypt", "sign", "verify", "deriveKey", "deriveBits", "wrapKey", "unwrapKey"]
);
공개 키 가져 오기 예제 (htps : //로 ゔぇぺぺr. 모잖아. 오 rg/쟈/도cs/우ぇb/아피/스 btぇCryp와/이 m포 rt케 y):
// from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
function str2ab(str) {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
const pemEncodedKey = `-----BEGIN PUBLIC KEY-----
.......
-----END PUBLIC KEY-----`;
function importRsaKey(pem) {
const pemHeader = "-----BEGIN PUBLIC KEY-----";
const pemFooter = "-----END PUBLIC KEY-----";
const pemContents = pem.substring(pemHeader.length, pem.length - pemFooter.length);
// base64 decode the string to get the binary data
const binaryDerString = window.atob(pemContents);
// convert from a binary string to an ArrayBuffer
const binaryDer = str2ab(binaryDerString);
return window.crypto.subtle.importKey(
"spki",
binaryDer,
{
name: "RSA-OAEP",
hash: "SHA-256"
},
true,
["encrypt"]
);
}
※SubtleCrypto.generateKey()로 생성하는 것도 가능합니다만, 일반적으로 먼저 OpenSSL등 사전에 생성한 공개키를 임포트한다고 생각됩니다.
· 암호화 : SubtleCrypto.encrypt()
function encryptMessage(publicKey, message) {
let enc = new TextEncoder();
let encoded = enc.encode(message);
return window.crypto.subtle.encrypt(
{
name: "RSA-OAEP"
},
publicKey,
encoded
);
}
서버 측 (Node.js) : 개인 키로 해독
복호에는 프라이빗 키의 임포트, 복호의 2개의 수속이 있습니다.
Node.js의 Crypto 모듈을 사용하고 싶지만 해독 할 수 없습니다.
htps : // 그래서 js. ORG / API / CRYP. html # cryp와 _ cryp와 _ p rip에서 crypt_p rip teke y_bup r
@peculiar/webcrypto를 사용하여 해독 할 수있었습니다.
webcrypto: htps : // 기주 b. 코 m / ぺ ぃ r
· 개인 키 가져 오기 : SubtleCrypto.importKey ()
node.jsconst webcrypto = require("@peculiar/webcrypto");
const crypto = new webcrypto.Crypto();
const {TextDecoder} = require('util');
const pemText = "xxxxx";
const pkcs8 = Buffer.from(pemText, "base64");
const key = crypto.subtle.importKey("pkcs8", pkcs8, { name: "RSA-OAEP", hash: "SHA-256" }, true, ["decrypt"]);
・복호:SubtleCrypto.decrypt()
node.jsconst decryptedStr = await crypto.subtle.decrypt("RSA-OAEP", key, Buffer.from(encryptedMessage, "base64"));
const result = new TextDecoder("utf-8").decode(new Uint8Array(decryptedStr ));
참고 : h tps : // s t c ゔ ぇ rf ぉ w. 코 m / 쿠에 s chion s / 56058153 / r-s-cryp chion-u th-cryp와 - Mozu-Gi ゔ ぇ s r-o-p 512
기타: 대칭 암호화 예(AES-GCM)
function encryptMessage(key, message) {
let enc = new TextEncoder();
let encoded = enc.encode(message);
iv = window.crypto.getRandomValues(new Uint8Array(12));
return window.crypto.subtle.encrypt(
{
name: "AES-GCM",
iv: iv
},
key,
encoded
);
}
이상
공개키로 암호화에는 공개키의 임포트와 암호화의 2개의 수속이 있습니다.
・공개키의 임포트:SubtleCrypto.importKey()
const result = crypto.subtle.importKey(
format, // raw(AESの鍵),pkcs8(RSAのプライベート鍵),spki(SubjectPublicKeyInfo:RSAまたはElliptic Curveの公開鍵),jwk(JSON Web Key)
keyData, // キーデータ。ArrayBuffer、TypedArray、JSONWebKeyオブジェクト
algorithm, // ①、RsaHashedImportParams :RSA-OAEP、RSA-PSS。②、EcKeyImportParams:ECDSA、ECDH。③、HmacImportParams :HMAC ④、{ "name": ALGORITHM }:AES-CTR, AES-CBC, AES-GCM、AES-KW。 ⑤、PBKDF2
extractable, // true/false。 SubtleCrypto.exportKey() or SubtleCrypto.wrapKey()メソッドを使うか
usages // ["encrypt", "decrypt", "sign", "verify", "deriveKey", "deriveBits", "wrapKey", "unwrapKey"]
);
공개 키 가져 오기 예제 (htps : //로 ゔぇぺぺr. 모잖아. 오 rg/쟈/도cs/우ぇb/아피/스 btぇCryp와/이 m포 rt케 y):
// from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
function str2ab(str) {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
const pemEncodedKey = `-----BEGIN PUBLIC KEY-----
.......
-----END PUBLIC KEY-----`;
function importRsaKey(pem) {
const pemHeader = "-----BEGIN PUBLIC KEY-----";
const pemFooter = "-----END PUBLIC KEY-----";
const pemContents = pem.substring(pemHeader.length, pem.length - pemFooter.length);
// base64 decode the string to get the binary data
const binaryDerString = window.atob(pemContents);
// convert from a binary string to an ArrayBuffer
const binaryDer = str2ab(binaryDerString);
return window.crypto.subtle.importKey(
"spki",
binaryDer,
{
name: "RSA-OAEP",
hash: "SHA-256"
},
true,
["encrypt"]
);
}
※SubtleCrypto.generateKey()로 생성하는 것도 가능합니다만, 일반적으로 먼저 OpenSSL등 사전에 생성한 공개키를 임포트한다고 생각됩니다.
· 암호화 : SubtleCrypto.encrypt()
function encryptMessage(publicKey, message) {
let enc = new TextEncoder();
let encoded = enc.encode(message);
return window.crypto.subtle.encrypt(
{
name: "RSA-OAEP"
},
publicKey,
encoded
);
}
서버 측 (Node.js) : 개인 키로 해독
복호에는 프라이빗 키의 임포트, 복호의 2개의 수속이 있습니다.
Node.js의 Crypto 모듈을 사용하고 싶지만 해독 할 수 없습니다.
htps : // 그래서 js. ORG / API / CRYP. html # cryp와 _ cryp와 _ p rip에서 crypt_p rip teke y_bup r
@peculiar/webcrypto를 사용하여 해독 할 수있었습니다.
webcrypto: htps : // 기주 b. 코 m / ぺ ぃ r
· 개인 키 가져 오기 : SubtleCrypto.importKey ()
node.jsconst webcrypto = require("@peculiar/webcrypto");
const crypto = new webcrypto.Crypto();
const {TextDecoder} = require('util');
const pemText = "xxxxx";
const pkcs8 = Buffer.from(pemText, "base64");
const key = crypto.subtle.importKey("pkcs8", pkcs8, { name: "RSA-OAEP", hash: "SHA-256" }, true, ["decrypt"]);
・복호:SubtleCrypto.decrypt()
node.jsconst decryptedStr = await crypto.subtle.decrypt("RSA-OAEP", key, Buffer.from(encryptedMessage, "base64"));
const result = new TextDecoder("utf-8").decode(new Uint8Array(decryptedStr ));
참고 : h tps : // s t c ゔ ぇ rf ぉ w. 코 m / 쿠에 s chion s / 56058153 / r-s-cryp chion-u th-cryp와 - Mozu-Gi ゔ ぇ s r-o-p 512
기타: 대칭 암호화 예(AES-GCM)
function encryptMessage(key, message) {
let enc = new TextEncoder();
let encoded = enc.encode(message);
iv = window.crypto.getRandomValues(new Uint8Array(12));
return window.crypto.subtle.encrypt(
{
name: "AES-GCM",
iv: iv
},
key,
encoded
);
}
이상
const webcrypto = require("@peculiar/webcrypto");
const crypto = new webcrypto.Crypto();
const {TextDecoder} = require('util');
const pemText = "xxxxx";
const pkcs8 = Buffer.from(pemText, "base64");
const key = crypto.subtle.importKey("pkcs8", pkcs8, { name: "RSA-OAEP", hash: "SHA-256" }, true, ["decrypt"]);
const decryptedStr = await crypto.subtle.decrypt("RSA-OAEP", key, Buffer.from(encryptedMessage, "base64"));
const result = new TextDecoder("utf-8").decode(new Uint8Array(decryptedStr ));
function encryptMessage(key, message) {
let enc = new TextEncoder();
let encoded = enc.encode(message);
iv = window.crypto.getRandomValues(new Uint8Array(12));
return window.crypto.subtle.encrypt(
{
name: "AES-GCM",
iv: iv
},
key,
encoded
);
}
이상
Reference
이 문제에 관하여(Web Crypto API: RSA 개인 키로 해독), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/chenglin/items/7c6c4085cc6c9faf543c텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)