@amazon-devices/keplercrypto
KeplerCrypto APIは、暗号化キーの読み取り、生成、管理などの一般的な暗号化操作を、業界標準のアルゴリズムを使用して実行できるようにする機能を提供します。
注: KeplerCrypto APIをシミュレーターで実行することはサポートされていません。
開始の手順
セットアップ
- package.jsonファイルの
dependenciesセクションに、以下のライブラリ依存関係を追加します。
"@amazon-devices/keplercrypto": " ~2.0,
使用方法
KeplerCrypto機能を使用しているソースファイルで、ターボモジュールから必要なデータ型をインポートします。
import {
AsymmetricAlgorithm,
AsymmetricKeyBuilder,
CbcContextBuilder,
CtrContextBuilder,
Crypto,
DigestAlgorithm,
EccCurve,
GcmContextBuilder,
KeyPurpose,
PrivateKey,
PublicKey,
SymmetricAlgorithm,
SymmetricKey,
} from '@amazon-devices/keplercrypto';
KeplerCryptoターボモジュールを利用するには、必ず初めにCryptoクラスをインスタンス化します。
/**
* Cryptoオブジェクトを作成します。
*/
const crypto = new Crypto();
次のコード例は説明用であり、わかりやすいよう簡略化されています。KeplerCrypto APIのほとんどのメソッドは、エラーが発生すると例外をスローします。
呼び出しをtry-catchブロックでラップすると、発生したエラーを適切に処理できます。
try {
crypto.getRandom(length);
} catch (e) {
if (e instanceof InvalidArgumentError) {...}
else if (e instanceof SecurityError) {...}
}
特定のメソッドがスローする特定の例外については、ドキュメントを確認してください。
ECDSAの署名と検証
次のサンプルコードには、ECDSAキーペアの生成、メッセージ署名、検証が含まれています。
手順1: ECDSAキービルダーを作成する
// 新しいECDSAキービルダーを作成します
const keyBuilder = crypto.makeEccKeyBuilder();
// キーをエクスポート可能としてマークします
keyBuilder.exportable = true;
// キーの目的を設定します
keyBuilder.purposes = [KeyPurpose.SIGN, KeyPurpose.VERIFY];
手順2: キーペアを生成する
ECDSAキーペアを生成するか、プライベートキーを作成できます。
ECDSAキーペアを生成するには、buildGenerated()を呼び出します。
// ECDSAキーペアを生成します
const privateKey = await keyBuilder.buildGenerated();
// パブリックキーを取得します
const publicKey = privateKey.getPublicKey();
既存のDER文字列からプライベートキーを作成するには、buildPrivateFromDer()を呼び出します。
// 既存のDER文字列からプライベートキーを作成します
const privateKey = await keyBuilder.buildPrivateFromDer(privateKeyDer);
const publicKey = privateKey.getPublicKey();
</viv>
手順3: 署名コンテキストビルダーを作成する
const builder = crypto.makeSignatureContextBuilder();
builder.signingAlgorithm = crypto.getAsymmetricAlgorithmByName(AsymmetricAlgorithm.ECDSA);
手順4: メッセージに署名して署名を取得する
// プライベートキーを使用して署名コンテキストを作成します
const signer = builder.buildSigningContext(privateKey);
const message = 'This is a very important message';
const messageBuffer = new TextEncoder().encode(message).buffer;
// メッセージに署名します
const signedMessage = await signer.sign(messageBuffer);
手順5: 署名付きのメッセージを検証する
// パブリックキーを使用して検証コンテキストを作成します
const verifier = builder.buildVerificationContext(publicKey);
// メッセージを検証します
const result = await verifier.verify(messageBuffer, signedMessage);
RSAの署名と検証
次のサンプルコードには、RSAキーペアの生成、メッセージ署名、検証が含まれています。
手順1: RSAキービルダーを作成する
// RSAキービルダーを作成します
const keybuilder = crypto.makeRsaKeyBuilder();
// キーをエクスポート可能としてマークします
keyBuilder.exportable = true;
// キーの目的を設定します
keyBuilder.purposes = [KeyPurpose.SIGN, KeyPurpose.VERIFY];
手順2: キーペアを生成する
RSAキーペアを生成するか、プライベートキーを作成できます。
RSAキーペアを生成するには、buildGenerated()を呼び出します。
// RSAキーペアを生成します
const privateKey = await keyBuilder.buildGenerated();
// パブリックキーを取得します
const publicKey = privateKey.getPublicKey();
既存のDER文字列からプライベートキーを作成するには、buildPrivateFromDer()を呼び出します。
// 既存のDER文字列からプライベートキーを作成します
const privateKey = await keyBuilder.buildPrivateFromDer(privateKeyDer);
const publicKey = privateKey.getPublicKey();
手順3: 署名コンテキストビルダーを作成してメッセージに署名する
buildSigningContext()を呼び出して署名コンテキストビルダーを作成した後、RSA-PKCS1 v1.5スキームを使用してメッセージに署名し、署名を取得します。
// プライベートキーを使用して署名コンテキストを作成します
const builder = crypto.makeRsassaPkcs1ContextBuilder();
const digestAlgorithm = crypto.getDigestAlgorithmByName(DigestAlgorithm.SHA256);
builder.digestAlgorithm = digestAlgorithm;
const rsaPkcs1Signer = builder.buildSigningContext(privateKey);
const message = 'This is a very important message';
const messageBuffer = new TextEncoder().encode(message).buffer;
// メッセージに署名します
const signedMessage = await rsaPkcs1Signer.sign(messageBuffer);
手順4: メッセージを検証する
RSA-PKCS1 v1.5標準を使用するrsaPkcs1Verifier.verify()を呼び出すことにより、署名を使用してメッセージを検証します。
// パブリックキーを使用して検証コンテキストを作成します
const rsaPkcs1Verifier = builder.buildVerificationContext(publicKey);
// メッセージを検証します
const result = await rsaPkcs1Verifier.verify(messageBuffer, signedMessage);
手順5: メッセージに署名して署名を取得する
RSA-PSS標準を使用してメッセージに署名するには、rsaPssSigner.sign()を呼び出します。これは、署名されたメッセージの署名を返します。
// 適切にパディングし、セキュリティを確保するため、ソルトの長さは、一般にダイジェストの長さと同じにする必要があります。
// 異なる長さのソルトを使用しても動作する可能性はありますが、推奨されません。
builder.saltLength = digestAlgorithm.size / 8;
// プライベートキーを使用して署名コンテキストを作成します
const rsaPssSigner = builder.buildSigningContext(privateKey);
const message = 'This is a very important message';
const messageBuffer = new TextEncoder().encode(message).buffer;
// メッセージに署名します
const signedMessage = await rsaPssSigner.sign(messageBuffer);
メッセージを検証するには、rsaPssVerifier.verify()を呼び出し、メッセージの署名を渡します。
// パブリックキーを使用して検証コンテキストを作成します
const rsaPssVerifier = builder.buildVerificationContext(publicKey);
// メッセージを検証します
const result = await rsaPssVerifier.verify(messageBuffer, signedMessage);
HMACの署名と検証
次の例は、シークレットキーを生成してキーをエクスポートし、データに署名した後、検証する方法を示しています。
// シークレットキーを生成します
const keyBuilder = crypto.makeSymmetricKeyBuilder();
keyBuilder.exportable = true;
keyBuilder.purposes = [KeyPurpose.ENCRYPT, KeyPurpose.DECRYPT];
keyBuilder.bits = 256;
const key = await keyBuilder.buildGenerated();
// セキュアキーをエクスポートします
const rawKey = key.exportRaw();
const exportedKeyBuilder = crypto.makeSymmetricKeyBuilder();
exportedKeyBuilder.exportable = true;
exportedKeyBuilder.purposes = [KeyPurpose.ENCRYPT, KeyPurpose.DECRYPT];
const exportedKey = await exportedKeyBuilder.buildFromRaw(rawKey);
// ダイジェストアルゴリズムを取得します
const digestAlgorithm = crypto.getDigestAlgorithmByName(DigestAlgorithm.SHA256);
// セキュアキーとダイジェストアルゴリズムを使用してHMACコンテキストビルダーを作成します
const builder = crypto.makeHmacContextBuilder();
builder.key = key;
builder.digestAlgorithm = digestAlgorithm;
// データに署名します
const signContext = builder.build();
const tag = await signContext.sign(plaintext);
// データを検証します
const verifyContext = builder.build();
const tag = signContext.sign(plaintext);
const result1 = await verifyContext.verify(plaintext, tag);
// エクスポートしたキーで検証を試行します
const exportedBuilder = crypto.makeHmacContextBuilder();
exportedBuilder.key = exportedKey;
exportedBuilder.digestAlgorithm(digestAlgorithm);
const exportedVerifyContext = exportedBuilder.build();
const result2 = await exportedVerifyContext.verify(plaintext, tag);
AES CBCブロック暗号を使用したメッセージの暗号化
次の例は、AES-256キーを生成してエクスポートし、AES-256 CBC暗号コンテキストビルダーを作成した後、そのコンテキストビルダーを使用してプレーンテキストに署名する方法を示しています。
// AES-256キーを生成します
const keyBuilder = crypto.makeSymmetricKeyBuilder();
keyBuilder.bits = 256;
keyBuilder.exportable = true;
const purposes = [KeyPurpose.ENCRYPT, KeyPurpose.DECRYPT];
keyBuilder.purposes = purposes;
const key = await keyBuilder.buildGenerated();
// AESキーをエクスポートします
const rawKey = key.exportRaw();
const exportedKeyBuilder = crypto.makeSymmetricKeyBuilder();
exportedKeyBuilder.exportable = true;
exportedKeyBuilder.purposes = purposes;
const exportedKey = await exportedKeyBuilder.buildFromRaw(rawKey);
// AES-256 CBC暗号コンテキストビルダーを作成します
const builder = crypto.makeCbcCipherContextBuilder(crypto.getSymmetricAlgorithmByName(SymmetricAlgorithm.AES256));
// 適切なIVを設定します
const iv = new Uint8Array(builder.ivSize).buffer;
builder.iv = iv;
// キーを設定します
builder.key = key;
// プレーンテキストを暗号化します
const plaintext = 'try this string';
const plaintextBuffer = new TextEncoder().encode(plaintext).buffer;
const encryptionContext = builder.buildEncryptionContext();
const ciphertext = await encryptionContext.encrypt(plaintextBuffer);
// 暗号文を復号化します
const decryptionContext = builder.buildDecryptionContext();
const decrypted = await decryptionContext.decrypt(ciphertext);
// エクスポートしたキーを使用した後、そのキーを使用して暗号文の復号化を試行します
const exportedBuilder = crypto.makeCbcCipherContextBuilder(crypto.getSymmetricAlgorithmByName(SymmetricAlgorithm.AES256));
exportedBuilder.iv = iv;
exportedBuilder.key = exportedKey;
const exportedDecryptionContext = exportedBuilder.buildDecryptionContext();
const exportedDecrypted = await exportedDecryptionContext.decrypt(ciphertext);
AES CTRブロック暗号を使用したメッセージの暗号化
次の例は、AES-CTRキーを生成してエクスポートし、AES-256 CTR暗号コンテキストビルダーを作成した後、そのコンテキストビルダーを使用してプレーンテキストに署名する方法を示しています。
// AES-256キーを生成します
const purposes = [KeyPurpose.ENCRYPT, KeyPurpose.DECRYPT];
const keyBuilder = crypto.makeSymmetricKeyBuilder();
keyBuilder.exportable = true;
keyBuilder.purposes = purposes;
keyBuilder.bits = 256;
const key = await keyBuilder.buildGenerated();
// AESキーをエクスポートします
const rawKey = key.exportRaw();
const exportedKeyBuilder = crypto.makeSymmetricKeyBuilder();
exportedKeyBuilder.exportable = true;
exportedKeyBuilder.purposes = purposes;
const exportedKey = await exportedKeyBuilder.buildFromRaw(rawKey);
// AES CTR暗号コンテキストビルダーを作成します
const builder = crypto.makeCtrCipherContextBuilder(crypto.getSymmetricAlgorithmByName(SymmetricAlgorithm.AES256));
// 適切なカウントとノンスを設定します
builder.count = 12;
builder.nonce = 12;
// キーを設定します
builder.key = key;
// プレーンテキストを暗号化します
const plaintext = 'try this string';
const plaintextBuffer = new TextEncoder().encode(plaintext).buffer;
const encryptionContext = builder.buildEncryptionContext();
const ciphertext = await encryptionContext.encrypt(plaintextBuffer);
// 暗号文を復号化します
const decryptionContext = builder.buildDecryptionContext();
const decrypted = await decryptionContext.decrypt(ciphertext);
const result1 = plaintext === new TextDecoder('utf-8').decode(decrypted);
// エクスポートしたキーをCTR暗号コンテキストビルダーで使用します
builder.key = exportedKey;
// エクスポートしたキーを使用して復号化を試行します
const exportedDecryptionContext = builder.buildDecryptionContext();
const exportedDecrypted = await exportedDecryptionContext.decrypt(ciphertext);
const result2 = plaintext === new TextDecoder('utf-8').decode(exportedDecrypted);
AES GCMブロック暗号を使用したメッセージの暗号化
次の例は、AES-256 GCMキーを生成してエクスポートし、AES-256 GCM暗号コンテキストビルダーを作成した後、そのコンテキストビルダーを使用してプレーンテキストに署名する方法を示しています。
// AES-256キーを生成します
const purposes = [KeyPurpose.ENCRYPT, KeyPurpose.DECRYPT];
const keyBuilder = crypto.makeSymmetricKeyBuilder();
keyBuilder.exportable = true;
keyBuilder.purposes = purposes;
keyBuilder.bits = 256;
const key = await keyBuilder.buildGenerated();
// AESキーをエクスポートします
const rawKey = key.exportRaw();
const exportedKeyBuilder = crypto.makeSymmetricKeyBuilder();
exportedKeyBuilder.exportable = true;
exportedKeyBuilder.purposes = purposes;
const exportedKey = await exportedKeyBuilder.buildFromRaw(rawKey);
// AES-256 GCM暗号コンテキストビルダーを作成します
const builder = crypto.makeGcmCipherContextBuilder(crypto.getSymmetricAlgorithmByName(SymmetricAlgorithm.AES256));
// ランダム化されたノンスのシーケンスを使用するために、IVを
// 4バイトの識別子で初期化します。または、サイズがbuilder.getIvSize()のベクトルを使用して初期化し
// 任意のノンスを使用します。
const iv = new Uint8Array([0xab, 0xcd, 0xef, 0x01]);
builder.iv = iv;
builder.key = key;
// プレーンテキストを暗号化します
const plaintext = 'try this string';
const plaintextBuffer = new TextEncoder().encode(plaintext).buffer;
const encryptionContext = builder.buildEncryptionContext();
const ciphertext = await encryptionContext.encrypt(plaintextBuffer);
// 暗号文を復号化します
const decryptionContext = builder.buildDecryptionContext();
const decrypted = await decryptionContext.decrypt(ciphertext);
// エクスポートしたキーをGCM暗号コンテキストビルダーで使用します
builder.key = exportedKey;
// エクスポートしたキーを使用して復号化を試行します
const exportedDecryptionContext = builder.buildDecryptionContext();
const exportedDecrypted = await exportedDecryptionContext.decrypt(ciphertext);
RSA-OAEPを使用したメッセージの暗号化
次の例は、RSA-OAEPキーを生成してエクスポートし、コンテキストビルダーを作成した後、そのコンテキストビルダーを使用してプレーンテキストに署名する方法を示しています。
// ダイジェストアルゴリズムと非対称アルゴリズムを取得し、キーの目的を定義します
const sha = crypto.getDigestAlgorithmByName(DigestAlgorithm.SHA384);
const alg = crypto.getAsymmetricAlgorithmByName(AsymmetricAlgorithm.RSA_OAEP);
const purposes = [KeyPurpose.ENCRYPT, KeyPurpose.DECRYPT];
// RsaOaepKeyBuilderを作成します
const keyBuilder = crypto.makeRsaOaepKeyBuilder();
keyBuilder.exportable = true;
keyBuilder.purposes = purposes;
keyBuilder.bits = 384;
// キービルダーからプライベートキーを生成します
const privateKey = await keyBuilder.buildGenerated();
// 後のテストケース用にキーをエクスポートします
const rawPrivateKey = await privateKey.exportDer();
// 対応するパブリックキーを取得します
const publicKey = privateKey.getPublicKey();
// 後で使用するためにパブリックキーをエクスポートします
const rawPublicKey = await publickey.exportDer();
// メッセージからプレーンテキストを作成します
const plaintext = 'try this string';
const plaintextBuffer = new TextEncoder().encode(plaintext).buffer;
// algとshaを使用してRSA-OAEP暗号コンテキストを作成します
const rsaOaepCipherContext = crypto.makeRsaOaepCipherContextBuilder(alg, sha);
// パブリックキーを使用してRSA-OAEP暗号コンテキストから暗号化コンテキストを作成します
const rsaOaepEncryptionContext = rsaOaepCipherContext.buildEncryptionContext(publickey);
// 暗号化コンテキストを使用して暗号化します
const ciphertext = await rsaOaepEncryptionContext.encrypt(plaintextBuffer);
// 暗号コンテキストから復号コンテキストを作成します
const rsaOaepDecryptionContext = rsaOaepCipherContext.buildDecryptionContext(privatekey);
// 復号コンテキストを使用して復号化します
const decrypted = await rsaOaepDecryptionContext.decrypt(ciphertext);
// 復号化されたメッセージがプレーンテキストと同じであることを確認します
const result1 = plaintext === new TextDecoder('utf-8').decode(decrypted);
// エクスポートしたキーを使用してプライベートキーとパブリックキーを作成します
const exportedPrivkey = await keyBuilder.buildPrivateFromDer(rawPrivateKey);
const exportedRsaOaepDecryptionContext = rsaOaepCipherContext.buildDecryptionContext(exportedPrivkey);
// インポートしたキーを使用して暗号文を復号化し、復号化されたメッセージがプレーンテキストと同じであることを確認します
const exportedDecrypted = await exportedRsaOaepDecryptionContext.decrypt(ciphertext);
const result2 = plaintext === new TextDecoder('utf-8').decode(exportedDecrypted);
// インポートしたパブリックキーを使用して暗号化し、元のプライベートキーを使用して復号化して、
// 復号化されたメッセージがプレーンテキストと同じであることを確認します
const exportedPublicKey = await keyBuilder.buildPublicFromDer(rawPublicKey);
const exportedRsaOaepEncryptionContext = rsaOaepCipherContext.buildEncryptionContext(exportedPublicKey);
const exportedCiphertext = await exportedRsaOaepEncryptionContext.encrypt(plaintextBuffer);
const exportedDecryptedAgain = await rsaOaepDecryptionContext.decrypt(exportedCiphertext);
const result3 = plaintext === new TextDecoder('utf-8').decode(exportedDecryptedAgain);
メッセージダイジェストの作成
次のコード例では、getDigestAlgorithmByName()を呼び出してダイジェストを取得し、ダイジェストコンテキストを作成した後、サンプル文字列をエンコードして、その文字列のダイジェストを取得しています。
const builder = crypto.makeDigestContextBuilder();
builder.digestAlgorithm = crypto.getDigestAlgorithmByName(DigestAlgorithm.SHA256);
const digestContext = builder.build();
const plaintext = 'try this string';
const plaintextBuffer = new TextEncoder().encode(plaintext).buffer;
const hash = await digestContext.digest(plaintextBuffer);
HKDF(HMACキー導出関数)を使用したキー導出
const salt = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const info = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // キーからの追加情報
// シークレットを作成します(導出目的のシークレットが既にある場合は省略可能)
const keyBuilder = crypto.makeSymmetricKeyBuilder();
keyBuilder.bits = 256; // 任意の長さ
keyBuilder.exportable = false;
keyBuilder.purposes = [KeyPurpose.DERIVE]; // 重要:シークレットで導出できる必要があります
const secret = await keyBuilder.buildGenerated();
const algorithm = crypto.getDigestAlgorithmByName(DigestAlgorithm.SHA256);
// コンテキストビルダーを作成します
const ctxBuilder = crypto.makeHkdfContextBuilder();
ctxBuilder.info = info;
ctxBuilder.salt = salt;
ctxBuilder.hashAlgorithm = algorithm;
// 導出コンテキストを作成します
const ctx = ctxBuilder.buildKeyDerivationContext(secret);
// 対称キーを生成します
// 重要:導出されたキーは、使用されているアルゴリズムの長さと一致する必要があります
const generatedKeyLen = algorithm.size / 8;
const symmKey = ctx.deriveKey(generatedKeyLen);
// 代わりにrawキーを生成します
const rawKey = ctx.deriveBits(generatedKeyLen);
PBKDF2(パスワードベースのキー導出関数2)を使用したキー導出
const iterations = 10000; // イテレーション回数。最大値にすると最も安全になりますが、パフォーマンスの低下も最大になります。
// 10000はパフォーマンスがそれほど低下しない適切な値です
const salt = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const generatedKeyLen = 512;
// コンテキストビルダーを作成します
const ctxBuilder = crypto.makePbkdf2ContextBuilder();
// シークレットを作成します(導出目的のシークレットが既にある場合は省略可能)
const keyBuilder = crypto.makeSymmetricKeyBuilder()
keyBuilder.bits = 256; // 任意の長さ
keyBuilder.exportable = false;
keyBuilder.purposes = [KeyPurpose.DERIVE]; // 重要:シークレットで導出できる必要があります
const secret = await keyBuilder.buildGenerated();
const algorithm = crypto.getDigestAlgorithmByName(DigestAlgorithm.SHA256);
// 導出コンテキストを作成します
ctxBuilder.iterations = iterations;
ctxBuilder.salt = salt;
ctxBuilder.hashAlgorithm = algorithm;
const ctx = buildKeyDerivationContext(secret);
// 対称キーを生成します
const symmKey = await ctx.deriveKey(generatedKeyLen);
// 代わりにrawキーを生成します
const rawKey = await ctx.deriveBits(generatedKeyLen);
Web Crypto APIシムレイヤー
KeplerCryptoライブラリは、Web Crypto APIを実装するシムレイヤーを提供します。APIのメソッドとパラメーターについては、既存のWeb Crypto APIに関するMDNのドキュメントを参照しています。
Web Cryptoの使用例
次の例は、Web Crypto APIシムレイヤーをインポートして使用する方法を示しています。
APIのインポート
import {WebCrypto} from '@amazon-devices/keplercrypto';
WebCryptoオブジェクトの初期化
const wc = new WebCrypto();
省略可能: globalThisへのcryptoインスタンスの公開
// globalThisが存在しない場合は定義します
if (typeof globalThis === 'undefined') {
(window as any).globalThis = window;
}
globalThis.crypto = wc.crypto as any;
Web Crypto APIの呼び出し
次のコード例では、ECDH CryptoKeyPairを生成します。
const nonExtractableKeyPair = (await wc.crypto.subtle.generateKey(
{
name: 'ECDH',
namedCurve: 'P-256',
},
false, // 抽出不可
['deriveBits'],
)) as CryptoKeyPair;
サポートされているWeb Cryptoアルゴリズム
このライブラリは現在開発中であり、このWeb Cryptoの実装ではW3C Web Crypto仕様全体のサブセットが提供されます。今後のバージョンで、より多くの操作がサポートされる予定です。
注:deriveKeyは、Web Cryptoシムレイヤーの実装ではサポートされていません。
キー導出機能については、上記の「HKDFを使用したキー導出」および「PBKDF2を使用したキー導出」の例に示すように、標準のKeplerCrypto APIを使用してください。
Web Cryptoでサポートされているキー形式
Web Crypto APIを使用してキーをインポートおよびエクスポートする場合、次の形式がサポートされます。
| キータイプ | サポートされているインポート形式 | サポートされているエクスポート形式 |
|---|---|---|
| AES | raw、jwk | raw、jwk |
| HMAC | raw、jwk | raw、jwk |
| ECDH | pkcs8、spki、jwk | pkcs8、spki、jwk |
形式の説明:
- raw: 対称キー(AESまたはHMAC)または楕円曲線パブリックキーに使用されるフォーマットされていないバイナリデータ。
- pkcs8: RSAまたは楕円曲線プライベートキーに使用されるPKCS #8形式。
- spki: RSAまたは楕円曲線パブリックキーに使用されるSubjectPublicKeyInfo形式。
- jwk: JSONウェブキー形式(すべてのキータイプでサポートされます)。
キーのインポートの例:
// AESキーをraw形式でインポートします
const rawKey = new Uint8Array([...]); // 使用するキーバイト
const importedKey = await wc.crypto.subtle.importKey(
"raw", // 形式
rawKey, // キーデータ
{ name: "AES-GCM" }, // アルゴリズム
false, // 抽出可能
["encrypt", "decrypt"] // キーの用途
);
Web Crypto APIのサポートマトリックス
アルゴリズム操作:
- ✓ = サポート
- ✗ = 非サポート
| アルゴリズム | encrypt() | decrypt() | sign() | verify() | digest() | deriveKey() | importKey() | exportKey() | deriveBits() | generateKey() |
|---|---|---|---|---|---|---|---|---|---|---|
| RSASSA-PKCS1v1 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| RSA-PSS | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| RSA-OAEP | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| ECDH | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | ✓ | ✓ |
| ECDSA | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| AES-CTR | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✓ |
| AES-CBC | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✓ |
| AES-GCM | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✓ |
| HMAC | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ |
| SHA-1 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ |
| SHA-256 | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| SHA-384 | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| SHA-512 | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| HKDF | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| PBKDF2 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
KeplerCryptoの概要
KeplerCrypto APIは、暗号化キーの読み取り、生成、管理などの一般的な暗号化操作を、業界標準のアルゴリズムを使用して実行できるようにする機能を提供します。
開始の手順
KeplerCrypto APIはKepler SDKの一部として提供されています。
KeplerCryptoのインストールとセットアップ
このAPIをプロジェクトに追加するには、アプリのルートディレクトリにあるpackage.jsonファイルを開き、次の依存関係を追加します。
"dependencies": {
"@amazon-devices/keplercrypto": "*",
...
},
アプリでのKeplerCrypto APIの使用
KeplerCrypto機能を使用しているソースファイルで、ターボモジュールから必要なデータ型をインポートします。
import {
AsymmetricAlgorithm,
AsymmetricKeyBuilder,
CbcContextBuilder,
CtrContextBuilder,
Crypto,
DigestAlgorithm,
EccCurve,
GcmContextBuilder,
KeyPurpose,
PrivateKey,
PublicKey,
SymmetricAlgorithm,
SymmetricKey,
} from '@amazon-devices/keplercrypto';
次に、Cryptoインスタンスを取得します。
/**
* Cryptoオブジェクトを作成します。
*/
const crypto = new Crypto();
KeplerCryptoターボモジュールを利用するには、必ず初めにCryptoクラスをインスタンス化します。
KeplerCrypto common use cases
次のコード例は説明用であり、わかりやすいよう簡略化されています。KeplerCrypto APIのほとんどのメソッドは、エラーが発生すると例外をスローします。
呼び出しをtry-catchブロックでラップすると、発生したエラーを適切に処理できます。以下に例を示します。
try {
crypto.getRandom(length);
} catch (e) {
if (e instanceof InvalidArgumentError) {...}
else if (e instanceof SecurityError) {...}
}
呼び出すメソッドのドキュメントで、そのメソッドがスローする具体的な例外を確認してください。
注: このターボモジュールをシミュレーターで実行することはサポートされていません。
ECDSAの署名と検証
次のサンプルコードには、ECDSAキーペアの生成、メッセージ署名、検証が含まれています。
手順1: ECDSAキービルダーを作成する
// 新しいECDSAキービルダーを作成します
const keyBuilder = crypto.makeEccKeyBuilder();
// キーをエクスポート可能としてマークします
keyBuilder.exportable = true;
// キーの目的を設定します
keyBuilder.purposes = [KeyPurpose.SIGN, KeyPurpose.VERIFY];
手順2: キーペアを生成する
ECDSAキーペアを生成するか、プライベートキーを作成できます。
ECDSAキーペアを生成するには、buildGenerated()を呼び出します。
// ECDSAキーペアを生成します
const privateKey = await keyBuilder.buildGenerated();
// パブリックキーを取得します
const publicKey = privateKey.getPublicKey();
既存のDER文字列からプライベートキーを作成するには、buildPrivateFromDer()を呼び出します。
// 既存のDER文字列からプライベートキーを作成します
const privateKey = await keyBuilder.buildPrivateFromDer(privateKeyDer);
const publicKey = privateKey.getPublicKey();
手順3: 署名コンテキストビルダーを作成する
const builder = crypto.makeSignatureContextBuilder();
builder.signingAlgorithm = crypto.getAsymmetricAlgorithmByName(AsymmetricAlgorithm.ECDSA);
手順4: メッセージに署名して署名を取得する
// プライベートキーを使用して署名コンテキストを作成します
const signer = builder.buildSigningContext(privateKey);
const message = 'This is a very important message';
const messageBuffer = new TextEncoder().encode(message).buffer;
// メッセージに署名します
const signedMessage = await signer.sign(messageBuffer);
手順5: 署名付きのメッセージを検証する
// パブリックキーを使用して検証コンテキストを作成します
const verifier = builder.buildVerificationContext(publicKey);
// メッセージを検証します
const result = await verifier.verify(messageBuffer, signedMessage);
RSAの署名と検証
次のサンプルコードには、RSAキーペアの生成、メッセージ署名、検証が含まれています。
手順1: RSAキービルダーを作成する
// RSAキービルダーを作成します
const keybuilder = crypto.makeRsaKeyBuilder();
// キーをエクスポート可能としてマークします
keyBuilder.exportable = true;
// キーの目的を設定します
keyBuilder.purposes = [KeyPurpose.SIGN, KeyPurpose.VERIFY];
手順2: キーペアを生成する
RSAキーペアを生成するか、プライベートキーを作成できます。
RSAキーペアを生成するには、buildGenerated()を呼び出します。
// RSAキーペアを生成します
const privateKey = await keyBuilder.buildGenerated();
// パブリックキーを取得します
const publicKey = privateKey.getPublicKey();
既存のDER文字列からプライベートキーを作成するには、buildPrivateFromDer()を呼び出します。
// 既存のDER文字列からプライベートキーを作成します
const privateKey = await keyBuilder.buildPrivateFromDer(privateKeyDer);
const publicKey = privateKey.getPublicKey();
手順3: 署名コンテキストビルダーを作成してメッセージに署名する
buildSigningContext()を呼び出して署名コンテキストビルダーを作成した後、RSA-PKCS1 v1.5スキームを使用してメッセージに署名し、署名を取得します。
// プライベートキーを使用して署名コンテキストを作成します
const builder = crypto.makeRsassaPkcs1ContextBuilder();
const digestAlgorithm = crypto.getDigestAlgorithmByName(DigestAlgorithm.SHA256);
builder.digestAlgorithm = digestAlgorithm;
const rsaPkcs1Signer = builder.buildSigningContext(privateKey);
const message = 'This is a very important message';
const messageBuffer = new TextEncoder().encode(message).buffer;
// メッセージに署名します
const signedMessage = await rsaPkcs1Signer.sign(messageBuffer);
手順4: メッセージを検証する
RSA-PKCS1 v1.5標準を使用するrsaPkcs1Verifier.verify()を呼び出すことにより、署名を使用してメッセージを検証します。
// パブリックキーを使用して検証コンテキストを作成します
const rsaPkcs1Verifier = builder.buildVerificationContext(publicKey);
// メッセージを検証します
const result = await rsaPkcs1Verifier.verify(messageBuffer, signedMessage);
手順5: メッセージに署名して署名を取得する
RSA-PSS標準を使用してメッセージに署名するには、rsaPssSigner.sign()を呼び出します。これは、署名されたメッセージの署名を返します。
// 適切にパディングし、セキュリティを確保するため、ソルトの長さは、一般にダイジェストの長さと同じにする必要があります。
// 異なる長さのソルトを使用しても動作する可能性はありますが、推奨されません。
builder.saltLength = digestAlgorithm.size / 8;
// プライベートキーを使用して署名コンテキストを作成します
const rsaPssSigner = builder.buildSigningContext(privateKey);
const message = 'This is a very important message';
const messageBuffer = new TextEncoder().encode(message).buffer;
// メッセージに署名します
const signedMessage = await rsaPssSigner.sign(messageBuffer);
メッセージを検証するには、rsaPssVerifier.verify()を呼び出し、メッセージの署名を渡します。
// パブリックキーを使用して検証コンテキストを作成します
const rsaPssVerifier = builder.buildVerificationContext(publicKey);
// メッセージを検証します
const result = await rsaPssVerifier.verify(messageBuffer, signedMessage);
HMACの署名と検証
次の例は、シークレットキーを生成してキーをエクスポートし、データに署名した後、検証する方法を示しています。
// シークレットキーを生成します
const keyBuilder = crypto.makeSymmetricKeyBuilder();
keyBuilder.exportable = true;
keyBuilder.purposes = [KeyPurpose.ENCRYPT, KeyPurpose.DECRYPT];
keyBuilder.bits = 256;
const key = await keyBuilder.buildGenerated();
// シークレットキーをエクスポートします
const rawKey = key.exportRaw();
const exportedKeyBuilder = crypto.makeSymmetricKeyBuilder();
exportedKeyBuilder.exportable = true;
exportedKeyBuilder.purposes = [KeyPurpose.ENCRYPT, KeyPurpose.DECRYPT];
const exportedKey = await exportedKeyBuilder.buildFromRaw(rawKey);
// ダイジェストアルゴリズムを取得します
const digestAlgorithm = crypto.getDigestAlgorithmByName(DigestAlgorithm.SHA256);
// セキュアキーとダイジェストアルゴリズムを使用してHMACコンテキストビルダーを作成します
const builder = crypto.makeHmacContextBuilder();
builder.key = key;
builder.digestAlgorithm = digestAlgorithm;
// データに署名します
const signContext = builder.build();
const tag = await signContext.sign(plaintext);
// データを検証します
const verifyContext = builder.build();
const tag = signContext.sign(plaintext);
const result1 = await verifyContext.verify(plaintext, tag);
// エクスポートしたキーで検証を試行します
const exportedBuilder = crypto.makeHmacContextBuilder();
exportedBuilder.key = exportedKey;
exportedBuilder.digestAlgorithm(digestAlgorithm);
const exportedVerifyContext = exportedBuilder.build();
const result2 = await exportedVerifyContext.verify(plaintext, tag);
AES CBCブロック暗号を使用したメッセージの暗号化
次の例は、AES-256キーを生成してエクスポートし、AES-256 CBC暗号コンテキストビルダーを作成した後、そのコンテキストビルダーを使用してプレーンテキストを暗号化する方法を示しています。
// AES-256キーを生成します
const keyBuilder = crypto.makeSymmetricKeyBuilder();
keyBuilder.bits = 256;
keyBuilder.exportable = true;
const purposes = [KeyPurpose.ENCRYPT, KeyPurpose.DECRYPT];
keyBuilder.purposes = purposes;
const key = await keyBuilder.buildGenerated();
// AESキーをエクスポートします
const rawKey = key.exportRaw();
const exportedKeyBuilder = crypto.makeSymmetricKeyBuilder();
exportedKeyBuilder.exportable = true;
exportedKeyBuilder.purposes = purposes;
const exportedKey = await exportedKeyBuilder.buildFromRaw(rawKey);
// AES-256 CBC暗号コンテキストビルダーを作成します
const builder = crypto.makeCbcCipherContextBuilder(crypto.getSymmetricAlgorithmByName(SymmetricAlgorithm.AES256));
// 適切なIVを設定します
const iv = new Uint8Array(builder.ivSize).buffer;
builder.iv = iv;
// キーを設定します
builder.key = key;
// プレーンテキストを暗号化します
const plaintext = 'try this string';
const plaintextBuffer = new TextEncoder().encode(plaintext).buffer;
const encryptionContext = builder.buildEncryptionContext();
const ciphertext = await encryptionContext.encrypt(plaintextBuffer);
// 暗号文を復号化します
const decryptionContext = builder.buildDecryptionContext();
const decrypted = await decryptionContext.decrypt(ciphertext);
const result1 = plaintext === new TextDecoder('utf-8').decode(decrypted);
// エクスポートしたキーを使用した後、そのキーを使用して暗号文の復号化を試行します
const exportedBuilder = crypto.makeCbcCipherContextBuilder(crypto.getSymmetricAlgorithmByName(SymmetricAlgorithm.AES256));
exportedBuilder.iv = iv;
exportedBuilder.key = exportedKey;
const exportedDecryptionContext = exportedBuilder.buildDecryptionContext();
const exportedDecrypted = await exportedDecryptionContext.decrypt(ciphertext);
AES CTRブロック暗号を使用したメッセージの暗号化
次の例は、AES-CTRキーを生成してエクスポートし、AES-256 CTR暗号コンテキストビルダーを作成した後、そのコンテキストビルダーを使用してプレーンテキストを暗号化する方法を示しています。
// AES-256キーを生成します
const purposes = [KeyPurpose.ENCRYPT, KeyPurpose.DECRYPT];
const keyBuilder = crypto.makeSymmetricKeyBuilder();
keyBuilder.exportable = true;
keyBuilder.purposes = purposes;
keyBuilder.bits = 256;
const key = await keyBuilder.buildGenerated();
// AESキーをエクスポートします
const rawKey = key.exportRaw();
const exportedKeyBuilder = crypto.makeSymmetricKeyBuilder();
exportedKeyBuilder.exportable = true;
exportedKeyBuilder.purposes = purposes;
const exportedKey = await exportedKeyBuilder.buildFromRaw(rawKey);
// AES CTR暗号コンテキストビルダーを作成します
const builder = crypto.makeCtrCipherContextBuilder(crypto.getSymmetricAlgorithmByName(SymmetricAlgorithm.AES256));
// 適切なカウントとノンスを設定します
builder.count = 12;
builder.nonce = 12;
// キーを設定します
builder.key = key;
// プレーンテキストを暗号化します
const plaintext = 'try this string';
const plaintextBuffer = new TextEncoder().encode(plaintext).buffer;
const encryptionContext = builder.buildEncryptionContext();
const ciphertext = await encryptionContext.encrypt(plaintextBuffer);
// 暗号文を復号化します
const decryptionContext = builder.buildDecryptionContext();
const decrypted = await decryptionContext.decrypt(ciphertext);
const result1 = plaintext === new TextDecoder('utf-8').decode(decrypted);
// エクスポートしたキーをCTR暗号コンテキストビルダーで使用します
builder.key = exportedKey;
// エクスポートしたキーを使用して復号化を試行します
const exportedDecryptionContext = builder.buildDecryptionContext();
const exportedDecrypted = await exportedDecryptionContext.decrypt(ciphertext);
const result2 = plaintext === new TextDecoder('utf-8').decode(exportedDecrypted);
AES GCMブロック暗号を使用したメッセージの暗号化
次の例は、AES-256 GCMキーを生成してエクスポートし、AES-256 GCM暗号コンテキストビルダーを作成した後、そのコンテキストビルダーを使用してプレーンテキストを暗号化する方法を示しています。
// AES-256キーを生成します
const purposes = [KeyPurpose.ENCRYPT, KeyPurpose.DECRYPT];
const keyBuilder = crypto.makeSymmetricKeyBuilder();
keyBuilder.exportable = true;
keyBuilder.purposes = purposes;
keyBuilder.bits = 256;
const key = await keyBuilder.buildGenerated();
// AESキーをエクスポートします
const rawKey = key.exportRaw();
const exportedKeyBuilder = crypto.makeSymmetricKeyBuilder();
exportedKeyBuilder.exportable = true;
exportedKeyBuilder.purposes = purposes;
const exportedKey = await exportedKeyBuilder.buildFromRaw(rawKey);
// AES-256 GCM暗号コンテキストビルダーを作成します
const builder = crypto.makeGcmCipherContextBuilder(crypto.getSymmetricAlgorithmByName(SymmetricAlgorithm.AES256));
// ランダム化されたノンスのシーケンスを使用するために、IVを
// 4バイトの識別子で初期化します。または、サイズがbuilder.getIvSize()のベクトルを使用して初期化し
// 任意のノンスを使用します。
const iv = new Uint8Array([0xab, 0xcd, 0xef, 0x01]);
builder.iv = iv;
builder.key = key;
// プレーンテキストを暗号化します
const plaintext = 'try this string';
const plaintextBuffer = new TextEncoder().encode(plaintext).buffer;
const encryptionContext = builder.buildEncryptionContext();
const ciphertext = await encryptionContext.encrypt(plaintextBuffer);
// 暗号文を復号化します
const decryptionContext = builder.buildDecryptionContext();
const decrypted = await decryptionContext.decrypt(ciphertext);
// エクスポートしたキーをGCM暗号コンテキストビルダーで使用します
builder.key = exportedKey;
// エクスポートしたキーを使用して復号化を試行します
const exportedDecryptionContext = builder.buildDecryptionContext();
const exportedDecrypted = await exportedDecryptionContext.decrypt(ciphertext);
RSA-OAEPを使用したメッセージの暗号化
次の例は、RSA-OAEPキーを生成してエクスポートし、コンテキストビルダーを作成した後、そのコンテキストビルダーを使用してプレーンテキストを暗号化する方法を示しています。
// ダイジェストアルゴリズムと非対称アルゴリズムを取得し、キーの目的を定義します
const sha = crypto.getDigestAlgorithmByName(DigestAlgorithm.SHA384);
const alg = crypto.getAsymmetricAlgorithmByName(AsymmetricAlgorithm.RSA_OAEP);
const purposes = [KeyPurpose.ENCRYPT, KeyPurpose.DECRYPT];
// RsaOaepKeyBuilderを作成します
const keyBuilder = crypto.makeRsaOaepKeyBuilder();
keyBuilder.exportable = true;
keyBuilder.purposes = purposes;
keyBuilder.bits = 384;
// キービルダーからプライベートキーを生成します
const privateKey = await keyBuilder.buildGenerated();
// 後のテストケース用にキーをエクスポートします
const rawPrivateKey = await privateKey.exportDer();
// 対応するパブリックキーを取得します
const publicKey = privateKey.getPublicKey();
// 後で使用するためにパブリックキーをエクスポートします
const rawPublicKey = await publickey.exportDer();
// メッセージからプレーンテキストを作成します
const plaintext = 'try this string';
const plaintextBuffer = new TextEncoder().encode(plaintext).buffer;
// algとshaを使用してRSA-OAEP暗号コンテキストを作成します
const rsaOaepCipherContext = crypto.makeRsaOaepCipherContextBuilder(alg, sha);
// パブリックキーを使用してRSA-OAEP暗号コンテキストから暗号化コンテキストを作成します
const rsaOaepEncryptionContext = rsaOaepCipherContext.buildEncryptionContext(publickey);
// 暗号化コンテキストを使用して暗号化します
const ciphertext = await rsaOaepEncryptionContext.encrypt(plaintextBuffer);
// 暗号コンテキストから復号コンテキストを作成します
const rsaOaepDecryptionContext = rsaOaepCipherContext.buildDecryptionContext(privatekey);
// 復号コンテキストを使用して復号化します
const decrypted = await rsaOaepDecryptionContext.decrypt(ciphertext);
// 復号化されたメッセージがプレーンテキストと同じであることを確認します
const result1 = plaintext === new TextDecoder('utf-8').decode(decrypted);
// エクスポートしたキーを使用してプライベートキーとパブリックキーを作成します
const exportedPrivkey = await keyBuilder.buildPrivateFromDer(rawPrivateKey);
const exportedRsaOaepDecryptionContext = rsaOaepCipherContext.buildDecryptionContext(exportedPrivkey);
// インポートしたキーを使用して暗号文を復号化し、復号化されたメッセージがプレーンテキストと同じであることを確認します
const exportedDecrypted = await exportedRsaOaepDecryptionContext.decrypt(ciphertext);
const result2 = plaintext === new TextDecoder('utf-8').decode(exportedDecrypted);
// インポートしたパブリックキーを使用して暗号化し、元のプライベートキーを使用して復号化して、
// 復号化されたメッセージがプレーンテキストと同じであることを確認します
const exportedPublicKey = await keyBuilder.buildPublicFromDer(rawPublicKey);
const exportedRsaOaepEncryptionContext = rsaOaepCipherContext.buildEncryptionContext(exportedPublicKey);
const exportedCiphertext = await exportedRsaOaepEncryptionContext.encrypt(plaintextBuffer);
const exportedDecryptedAgain = await rsaOaepDecryptionContext.decrypt(exportedCiphertext);
const result3 = plaintext === new TextDecoder('utf-8').decode(exportedDecryptedAgain);
メッセージダイジェストの作成
次のコード例では、getDigestAlgorithmByName()を呼び出してダイジェストを取得し、ダイジェストコンテキストを作成した後、サンプル文字列をエンコードして、その文字列のダイジェストを取得しています。
const builder = crypto.makeDigestContextBuilder();
builder.digestAlgorithm = crypto.getDigestAlgorithmByName(DigestAlgorithm.SHA256);
const digestContext = builder.build();
const plaintext = 'try this string';
const plaintextBuffer = new TextEncoder().encode(plaintext).buffer;
const hash = await digestContext.digest(plaintextBuffer);
HKDF(HMACキー導出関数)を使用したキー導出
const salt = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const info = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // キーからの追加情報
// シークレットを作成します(導出目的のシークレットが既にある場合は省略可能)
const keyBuilder = crypto.makeSymmetricKeyBuilder();
keyBuilder.bits = 256; // 任意の長さ
keyBuilder.exportable = false;
keyBuilder.purposes = [KeyPurpose.DERIVE]; // 重要:シークレットで導出できる必要があります
const secret = await keyBuilder.buildGenerated();
const algorithm = crypto.getDigestAlgorithmByName(DigestAlgorithm.SHA256);
// コンテキストビルダーを作成します
const ctxBuilder = crypto.makeHkdfContextBuilder();
ctxBuilder.info = info;
ctxBuilder.salt = salt;
ctxBuilder.hashAlgorithm = algorithm;
// 導出コンテキストを作成します
const ctx = ctxBuilder.buildKeyDerivationContext(secret);
// 対称キーを生成します
// 重要:導出されたキーは、使用されているアルゴリズムの長さと一致する必要があります
const generatedKeyLen = algorithm.size / 8;
const symmKey = ctx.deriveKey(generatedKeyLen);
// 代わりにrawキーを生成します
const rawKey = ctx.deriveBits(generatedKeyLen);
PBKDF2(パスワードベースのキー導出関数2)を使用したキー導出
const iterations = 10000; // 反復回数。値が大きいほどセキュリティは向上しますが、パフォーマンスは低下します。
// 10000はパフォーマンスがそれほど低下しない適切な値です
const salt = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const generatedKeyLen = 512;
// コンテキストビルダーを作成します
const ctxBuilder = crypto.makePbkdf2ContextBuilder();
// シークレットを作成します(導出目的のシークレットが既にある場合は省略可能)
const keyBuilder = crypto.makeSymmetricKeyBuilder()
keyBuilder.bits = 256; // 任意の長さ
keyBuilder.exportable = false;
keyBuilder.purposes = [KeyPurpose.DERIVE]; // 重要:シークレットで導出できる必要があります
const secret = await keyBuilder.buildGenerated();
const algorithm = crypto.getDigestAlgorithmByName(DigestAlgorithm.SHA256);
// 導出コンテキストを作成します
ctxBuilder.iterations = iterations;
ctxBuilder.salt = salt;
ctxBuilder.hashAlgorithm = algorithm;
const ctx = buildKeyDerivationContext(secret);
// 対称キーを生成します
const symmKey = await ctx.deriveKey(generatedKeyLen);
// 代わりにrawキーを生成します
const rawKey = await ctx.deriveBits(generatedKeyLen);
Web Crypto APIシムレイヤー
KeplerCryptoライブラリは、Web Crypto APIを実装するシムレイヤーを提供します。APIのメソッドとパラメーターについては、既存のWeb Crypto APIに関するMDNのドキュメントを参照しています。
Web Cryptoの使用例
次の例は、Web Crypto APIシムレイヤーをインポートして使用する方法を示しています。
APIのインポート
import {WebCrypto} from '@amazon-devices/keplercrypto';
WebCryptoオブジェクトの初期化
const wc = new WebCrypto();
省略可能: globalThisへのcryptoインスタンスの公開
// globalThisが存在しない場合は定義します
if (typeof globalThis === 'undefined') {
(window as any).globalThis = window;
}
globalThis.crypto = wc.crypto as any;
Web Crypto APIの呼び出し
次のコード例では、ECDH CryptoKeyPairを生成します。
const nonExtractableKeyPair = (await wc.crypto.subtle.generateKey(
{
name: 'ECDH',
namedCurve: 'P-256',
},
false, // 抽出不可
['deriveBits'],
)) as CryptoKeyPair;
サポートされているWeb Cryptoアルゴリズム
このライブラリは現在開発中であり、このWeb Cryptoの実装ではW3C Web Crypto仕様全体のサブセットが提供されます。今後のバージョンで、より多くの操作がサポートされる予定です。
Web Cryptoでサポートされているキー形式
Web Crypto APIを使用してキーをインポートおよびエクスポートする場合、次の形式がサポートされます。
| キータイプ | サポートされているインポート形式 | サポートされているエクスポート形式 |
|---|---|---|
| AES | raw、jwk | raw、jwk |
| HMAC | raw、jwk | raw、jwk |
| ECDH | pkcs8、spki、jwk | pkcs8、spki、jwk |
| ECDSA | pkcs8、spki、jwk | pkcs8、spki、jwk |
| HKDF | raw | raw |
| PBKDF2 | raw | raw |
| RSASSA-PKCS1-v1_5 | pkcs8、spki、jwk | pkcs8、spki、jwk |
| RSA-PSS | pkcs8、spki、jwk | pkcs8、spki、jwk |
| RSA-OAEP | pkcs8、spki、jwk | pkcs8、spki、jwk |
形式の説明:
- raw: 対称キーまたは楕円曲線パブリックキーに使用されるフォーマットされていないバイナリデータ。
- pkcs8: RSAまたは楕円曲線プライベートキーに使用されるPKCS #8形式。
- spki: RSAまたは楕円曲線パブリックキーに使用されるSubjectPublicKeyInfo形式。
- jwk: 対称キーまたはRSAおよび楕円曲線パブリック/プライベートキーに使用されるJSONウェブキー形式。
キーのインポートの例:
// AESキーをraw形式でインポートします
const rawKey = new Uint8Array([...]); // 使用するキーバイト
const importedKey = await wc.crypto.subtle.importKey(
"raw", // 形式
rawKey, // キーデータ
{ name: "AES-GCM" }, // アルゴリズム
false, // 抽出可能
["encrypt", "decrypt"] // キーの用途
);
Web Crypto APIのサポートマトリックス
アルゴリズム操作:
- ✓ = サポート
- ✗ = サポート対象外
- — = 該当なし
| アルゴリズム | encrypt() | decrypt() | sign() | verify() | digest() | importKey() | exportKey() | generateKey() | deriveBits() | deriveKey() | wrapKey() | unwrapKey() |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| RSASSA-PKCS1v1 | — | — | ✓ | ✓ | — | ✓ | ✓ | ✓ | — | — | — | — |
| RSA-PSS | — | — | ✓ | ✓ | — | ✓ | ✓ | ✓ | — | — | — | — |
| RSA-OAEP | ✓ | ✓ | — | — | — | ✓ | ✓ | ✓ | — | — | ✗ | ✗ |
| ECDH | — | — | — | — | — | ✓ | ✓ | ✓ | ✓ | ✓ | — | — |
| ECDSA | — | — | ✓ | ✓ | — | ✓ | ✓ | ✓ | — | — | — | — |
| AES-CTR | ✓ | ✓ | — | — | — | ✓ | ✓ | ✓ | — | — | ✗ | ✗ |
| AES-CBC | ✓ | ✓ | — | — | — | ✓ | ✓ | ✓ | — | — | ✗ | ✗ |
| AES-GCM | ✓ | ✓ | — | — | — | ✓ | ✓ | ✓ | — | — | ✗ | ✗ |
| AES-KW | — | — | — | — | — | ✗ | ✗ | ✗ | — | — | ✗ | ✗ |
| HMAC | — | — | ✓ | ✓ | — | ✓ | ✓ | ✓ | — | — | — | — |
| HKDF | — | — | — | — | — | ✓ | ✓ | — | ✓ | ✓ | — | — |
| PBKDF2 | — | — | — | — | — | ✓ | ✓ | — | ✓ | ✓ | — | — |
| Ed25519 | — | — | ✗ | ✗ | — | ✗ | ✗ | ✗ | — | — | — | — |
| X25519 | — | — | — | — | — | ✗ | ✗ | ✗ | ✗ | ✗ | — | — |
| SHA-1 | — | — | — | — | ✗ | — | — | — | — | — | — | — |
| SHA-256 | — | — | — | — | ✓ | — | — | — | — | — | — | — |
| SHA-384 | — | — | — | — | ✓ | — | — | — | — | — | — | — |
| SHA-512 | — | — | — | — | ✓ | — | — | — | — | — | — | — |
モジュール
- Crypto
- index
- turbo-modules/__mocks__/KeplerCrypto
- turbo-modules/__mocks__/KeplerCrypto
- turbo-modules/__mocks__/KeplerCrypto
- turbo-modules/KeplerCrypto
- turbo-modules/KeplerCrypto
- webcrypto/Crypto
- webcrypto/Crypto
- webcrypto/errors
- webcrypto/errors
- webcrypto/SubtleCrypto
- webcrypto/SubtleCrypto
- webcrypto/types
- webcrypto/types
- webcrypto/WebCrypto
- webcrypto/WebCrypto
Last updated: 2025年10月2日

