

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 原始 RSA 密钥环
<a name="use-raw-rsa-keyring"></a>

原始 RSA 密钥环使用您提供的 RSA 公有密钥和私有密钥为本地内存中的数据密钥执行非对称加密和解密。您需要生成、存储和保护私有密钥，最好是在硬件安全模块（HSM）或密钥管理系统中操作。加密功能对 RSA 公有密钥下的数据密钥进行加密。解密功能使用私有密钥对数据密钥进行解密。您可以从几种 [RSA 填充模式](https://github.com/aws/aws-encryption-sdk-c/blob/master/include/aws/cryptosdk/cipher.h)中进行选择。

加密和解密的原始 RSA 密钥环必须包含一个非对称公有密钥和私有密钥对。但是，您可以使用仅具有公有密钥的原始 RSA 密钥环加密数据，并使用仅具有私有密钥的原始 RSA 密钥环解密数据。您可以在[多重密钥环](use-multi-keyring.md)中包含任何原始 RSA 密钥环。如果您为原始 RSA 密钥环配置公有密钥和私有密钥，请确保其属于同一个密钥对。的某些语言实现 AWS Encryption SDK 不会使用来自不同对的密钥构建 Raw RSA 密钥环。其他语言实施则需要您验证密钥是否来自同一个密钥对。

 Raw RSA 密钥环与 RSA 非对称加密密钥一起使用 AWS Encryption SDK for Python 时，等同于 AWS Encryption SDK for Java 和[RawMasterKey](https://aws-encryption-sdk-python.readthedocs.io/en/latest/generated/aws_encryption_sdk.key_providers.raw.html#aws_encryption_sdk.key_providers.raw.RawMasterKey)中的密钥并与之互操作。[JceMasterKey](https://aws.github.io/aws-encryption-sdk-java/com/amazonaws/encryptionsdk/jce/JceMasterKey.html)您可以使用一种实现加密数据，用使用相同包装密钥的任何其他实现进行解密。有关更多信息，请参阅 [密钥环兼容性](choose-keyring.md#keyring-compatibility)。

**注意**  
原始 RSA 密钥环不支持非对称 KMS 密钥。如果要使用非对称 RSA KMS 密钥，则以下编程语言支持使用非对称 RSA 的 AWS KMS 密钥环： AWS KMS keys  
版本 3。 的 *x* AWS Encryption SDK for Java
版本 4。 .NET 的 *x* 及更高版本AWS Encryption SDK 
版本 4。 的 *x* AWS Encryption SDK for Python，与可选的[加密材料提供程序库](https://github.com/aws/aws-cryptographic-material-providers-library) (MPL) 依赖项一起使用时。
版本 0.1。 *x* 或更高版本的 fo AWS Encryption SDK r Go
如果您使用包含 RSA KMS 密钥公钥的 Raw RSA 密钥环对数据进行加密，则两者都 AWS Encryption SDK 无法 AWS KMS 对其进行解密。您无法将 AWS KMS 非对称 KMS 密钥的私钥导出到原始 RSA 密钥环中。 AWS KMS 解密操作无法解密返回的[加密消息](concepts.md#message)。 AWS Encryption SDK 

在中构建 Raw RSA 密钥环时 AWS Encryption SDK for C，请务必提供包含每个密钥的 PEM 文件的*内容*，以空结尾的 C 字符串，而不是路径或文件名。在 JavaScript 中构造原始 RSA 密钥环时，请注意与其他语言实施的[潜在不兼容性问题](javascript-compatibility.md)。

**命名空间和名称**

为标识密钥环中的 RSA 密钥材料，原始 AES 密钥环使用您提供的*命名空间*和*密钥名称*。这些值不是机密的。其以明文形式出现在加密操作返回的[加密消息](concepts.md#message)的标头中。我们建议在 HSM 或密钥管理系统中使用密钥命名空间与用于标识 RSA 密钥对（或其私有密钥）的密钥名称。

**注意**  
密钥命名空间和密钥名称等同于 `JceMasterKey` 和 `RawMasterKey` 中*提供程序 ID*（或*提供程序*）和*密钥 ID*字段。  
为 KMS `aws-kms` 密钥 AWS Encryption SDK for C 保留密钥命名空间值。请勿在原始 AES 密钥环或原始 RSA 密钥环中将其与 AWS Encryption SDK for C共用。

如果您通过构造不同的密钥环加密和解密给定消息，命名空间和名称值则至关重要。如果解密密钥环中的密钥命名空间和密钥名称与加密密钥环中的密钥命名空间和密钥名称不完全匹配、大小写不一致，即使密钥来自相同的密钥对，也不会使用解密密钥环。

无论密钥环中包含 RSA 公有密钥、RSA 私有密钥还是密钥对中的两个密钥，加密和解密密钥环中密钥材料的密钥命名空间和密钥名称必须相同。例如，假设您使用包含密钥命名空间 `HSM_01` 和密钥名称 `RSA_2048_06` 的 RSA 公有密钥的原始 RSA 密钥环加密数据。要解密数据，请使用私有密钥（或密钥对）、相同的密钥命名空间和名称构造原始 RSA 密钥环。

**填充模式**

您必须为用于加密和解密的原始 RSA 密钥环指定填充模式，或者使用为您指定填充模式的语言实施功能。

 AWS Encryption SDK 支持以下填充模式，受每种语言的限制。我们建议使用 [OAEP](https://tools.ietf.org/html/rfc8017#section-7.1) 填充模式，尤其是带有 SHA-256 和 MGF1 SHA-256 填充的 OAEP。仅支持[PKCS1](https://tools.ietf.org/html/rfc8017#section-7.2)填充模式是为了向后兼容。
+ 带有 SHA-1 和 MGF1 SHA-1 填充的 OAEP
+ 带有 SHA-256 和 MGF1 SHA-256 填充的 OAEP
+ 带有 SHA-384 和 MGF1 SHA-384 填充的 OAEP
+ 带有 SHA-512 和 MGF1 SHA-512 填充的 OAEP
+ PKCS1 v1.5 填充 

以下示例展示了如何使用 RSA 密钥对的公钥和私钥以及使用 SHA-256 和 MGF1 SHA-256 填充模式的 OAEP 创建原始 RSA 密钥环。`RSAPublicKey` 和 `RSAPrivateKey` 变量代表您提供的密钥材料。

------
#### [ C ]

要在中创建 RSA 原始密钥环 AWS Encryption SDK for C，请使用。`aws_cryptosdk_raw_rsa_keyring_new`

在中构建 Raw RSA 密钥环时 AWS Encryption SDK for C，请务必提供包含每个密钥的 PEM 文件的*内容*，以空结尾的 C 字符串，而不是路径或文件名。有关完整示例，请参阅 [raw\_rsa\_keyring.c](https://github.com/aws/aws-encryption-sdk-c/blob/master/examples/raw_rsa_keyring.c)。

```
struct aws_allocator *alloc = aws_default_allocator();

AWS_STATIC_STRING_FROM_LITERAL(key_namespace, "HSM_01");
AWS_STATIC_STRING_FROM_LITERAL(key_name, "RSA_2048_06");

struct aws_cryptosdk_keyring *rawRsaKeyring = aws_cryptosdk_raw_rsa_keyring_new(
    alloc,
    key_namespace,
    key_name,
    private_key_from_pem,
    public_key_from_pem,
    AWS_CRYPTOSDK_RSA_OAEP_SHA256_MGF1);
```

------
#### [ C\# / .NET ]

要在 AWS Encryption SDK 适用于.NET 的 Raw RSA 密钥环中实例化，请使用方法。`materialProviders.CreateRawRsaKeyring()`有关完整的示例，请参阅 [Raw RSAKeyring Example.cs](https://github.com/aws/aws-encryption-sdk/tree/mainline/AwsEncryptionSDK/runtimes/net/Examples/Keyring/RawRSAKeyringExample.cs)。

以下示例使用版本 4。 *x* 及更高版本 AWS Encryption SDK 适用于.NET。

```
// Instantiate the AWS Encryption SDK and material providers
var esdk =  new ESDK(new AwsEncryptionSdkConfig());
var mpl = new MaterialProviders(new MaterialProvidersConfig());

var keyNamespace = "HSM_01";
var keyName = "RSA_2048_06";

// Get public and private keys from PEM files
var publicKey = new MemoryStream(System.IO.File.ReadAllBytes("RSAKeyringExamplePublicKey.pem"));
var privateKey = new MemoryStream(System.IO.File.ReadAllBytes("RSAKeyringExamplePrivateKey.pem"));

// Create the keyring input
var createRawRsaKeyringInput = new CreateRawRsaKeyringInput
{
    KeyNamespace = keyNamespace,
    KeyName = keyName,
    PaddingScheme = PaddingScheme.OAEP_SHA512_MGF1,
    PublicKey = publicKey,
    PrivateKey = privateKey
};

// Create the keyring
var rawRsaKeyring = materialProviders.CreateRawRsaKeyring(createRawRsaKeyringInput);
```

------
#### [ JavaScript Browser ]

浏览器 AWS Encryption SDK for JavaScript 中的从库中获取其加密原语。[WebCrypto](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)在构造密钥环之前，必须使用`importPublicKey()` and/or `importPrivateKey()`将原始密钥材料导入 WebCrypto 后端。这样可以确保即使对的所有调用都是异步的，密钥环也是完整 WebCrypto 的。导入方法采用的对象包括包装算法及其填充模式。

导入密钥材料后，使用 `RawRsaKeyringWebCrypto()` 方法实例化密钥环。在中构建 Raw RSA 密钥环时 JavaScript，请注意[可能与其他语言实现不兼容](javascript-compatibility.md)。

以下示例使用`buildClient`函数来指定[默认的承诺策略](migrate-commitment-policy.md)`REQUIRE_ENCRYPT_REQUIRE_DECRYPT`。您也可以使用`buildClient`来限制加密消息中加密数据密钥的数量。有关更多信息，请参阅 [限制加密数据密钥](configure.md#config-limit-keys)。

有关完整的示例，请参阅 [rsa\_simple](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/example-browser/src/rsa_simple.ts) .ts（浏览器）。JavaScript 

```
import {
  RsaImportableKey,
  RawRsaKeyringWebCrypto,
  buildClient,
  CommitmentPolicy,
} from '@aws-crypto/client-browser'

const { encrypt, decrypt } = buildClient(
  CommitmentPolicy.{{REQUIRE_ENCRYPT_REQUIRE_DECRYPT}}
)

const privateKey = await RawRsaKeyringWebCrypto.importPrivateKey(
  privateRsaJwKKey
)

const publicKey = await RawRsaKeyringWebCrypto.importPublicKey(
  publicRsaJwKKey
)

const keyNamespace = '{{HSM_01}}'
const keyName = '{{RSA_2048_06}}'

const keyring = new RawRsaKeyringWebCrypto({
  keyName,
  keyNamespace,
  publicKey,
  privateKey,
})
```

------
#### [ JavaScript Node.js ]

要在 AWS Encryption SDK for JavaScript Node.js 中实例化原始 RSA 密钥环，请创建该类的新实例。`RawRsaKeyringNode``wrapKey` 参数用于保存公有密钥。`unwrapKey` 参数用于保存私有密钥。尽管您可以指定首选填充模式，但 `RawRsaKeyringNode` 构造函数会为您计算默认填充模式。

在中构造原始 RSA 密钥环时 JavaScript，请注意[可能与其他语言实现不兼容](javascript-compatibility.md)。

以下示例使用`buildClient`函数来指定[默认的承诺策略](migrate-commitment-policy.md)`REQUIRE_ENCRYPT_REQUIRE_DECRYPT`。您也可以使用`buildClient`来限制加密消息中加密数据密钥的数量。有关更多信息，请参阅 [限制加密数据密钥](configure.md#config-limit-keys)。

有关完整的示例，请参阅 [rsa\_simple](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/example-node/src/rsa_simple.ts) .ts (Node.js)。JavaScript 

```
import {
  RawRsaKeyringNode,
  buildClient,
  CommitmentPolicy,
} from '@aws-crypto/client-node'

const { encrypt, decrypt } = buildClient(
  CommitmentPolicy.{{REQUIRE_ENCRYPT_REQUIRE_DECRYPT}}
)

const keyNamespace = '{{HSM_01}}'
const keyName = '{{RSA_2048_06}}'

const keyring = new RawRsaKeyringNode({ keyName, keyNamespace, rsaPublicKey, rsaPrivateKey})
```

------
#### [ Java ]

```
final CreateRawRsaKeyringInput keyringInput = CreateRawRsaKeyringInput.builder()
        .keyName("{{RSA_2048_06}}")
        .keyNamespace("{{HSM_01}}")
        .paddingScheme(PaddingScheme.{{OAEP_SHA256_MGF1}})
        .publicKey({{RSAPublicKey}})
        .privateKey({{RSAPrivateKey}})
        .build();
final MaterialProviders matProv = MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();
IKeyring rawRsaKeyring = matProv.CreateRawRsaKeyring(keyringInput);
```

------
#### [ Python ]

以下示例使用[默认承诺策略](migrate-commitment-policy.md)实例化 AWS Encryption SDK 客户端。`REQUIRE_ENCRYPT_REQUIRE_DECRYPT`有关完整示例，请参阅中 AWS Encryption SDK for Python 存储库中的 [raw\_rsa\_keyring\_example.py](https://github.com/aws/aws-encryption-sdk-python/tree/master/examples/src/raw_rsa_keyring_example.py) GitHub。

```
# Define the key namespace and key name
key_name_space = "{{HSM_01}}"
key_name = "{{RSA_2048_06}}"

# Instantiate the material providers
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
    config=MaterialProvidersConfig()
)

# Create Raw RSA keyring
keyring_input: CreateRawRsaKeyringInput = CreateRawRsaKeyringInput(
    key_namespace=key_name_space,
    key_name=key_name,
    padding_scheme=PaddingScheme.{{OAEP_SHA256_MGF1}},
    public_key={{RSAPublicKey}},
    private_key={{RSAPrivateKey}}
)

raw_rsa_keyring: IKeyring = mat_prov.create_raw_rsa_keyring(
    input=keyring_input
)
```

------
#### [ Rust ]

```
// Instantiate the AWS Encryption SDK client
let esdk_config = AwsEncryptionSdkConfig::builder().build()?;
let esdk_client = esdk_client::Client::from_conf(esdk_config)?;

// Optional: Create an encryption context
let encryption_context = HashMap::from([
    ("encryption".to_string(), "context".to_string()),
    ("is not".to_string(), "secret".to_string()),
    ("but adds".to_string(), "useful metadata".to_string()),
    ("that can help you".to_string(), "be confident that".to_string()),
    ("the data you are handling".to_string(), "is what you think it is".to_string()),
]);

// Define the key namespace and key name
let key_namespace: &str = "{{HSM_01}}";
let key_name: &str = "{{RSA_2048_06}}";
                    
// Instantiate the material providers library
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;

// Create Raw RSA keyring
let raw_rsa_keyring = mpl
    .create_raw_rsa_keyring()
    .key_name(key_name)
    .key_namespace(key_namespace)
    .padding_scheme(PaddingScheme::{{OaepSha256Mgf1}})
    .public_key(aws_smithy_types::Blob::new({{RSAPublicKey}}))
    .private_key(aws_smithy_types::Blob::new({{RSAPrivateKey}}))
    .send()
    .await?;
```

------
#### [ Go ]

```
// Instantiate the material providers library
matProv, err := awscryptographymaterialproviderssmithygenerated.NewClient(awscryptographymaterialproviderssmithygeneratedtypes.MaterialProvidersConfig{})
                
// Create Raw RSA keyring
rsaKeyRingInput := awscryptographymaterialproviderssmithygeneratedtypes.CreateRawRsaKeyringInput{
	KeyName:       "rsa",
	KeyNamespace:  "rsa-keyring",
	PaddingScheme: awscryptographymaterialproviderssmithygeneratedtypes.PaddingSchemePkcs1,
	PublicKey:     pem.EncodeToMemory(publicKeyBlock),
	PrivateKey:    pem.EncodeToMemory(privateKeyBlock),
}

rsaKeyring, err := matProv.CreateRawRsaKeyring(context.Background(), rsaKeyRingInput)
```

------
#### [ Go ]

```
import (
    "context"
    
	mpl "aws/aws-cryptographic-material-providers-library/releases/go/mpl/awscryptographymaterialproviderssmithygenerated"
	mpltypes "aws/aws-cryptographic-material-providers-library/releases/go/mpl/awscryptographymaterialproviderssmithygeneratedtypes"
	client "github.com/aws/aws-encryption-sdk/awscryptographyencryptionsdksmithygenerated"
	esdktypes "github.com/aws/aws-encryption-sdk/awscryptographyencryptionsdksmithygeneratedtypes"
)

// Instantiate the AWS Encryption SDK client
encryptionClient, err := client.NewClient(esdktypes.AwsEncryptionSdkConfig{})
if err != nil {
    panic(err)
}

// Optional: Create an encryption context
encryptionContext := map[string]string{
    "encryption":                "context",
    "is not":                    "secret",
    "but adds":                  "useful metadata",
    "that can help you":         "be confident that",
    "the data you are handling": "is what you think it is",
}

// Define the key namespace and key name
var keyNamespace = "{{HSM_01}}"
var keyName = "{{RSA_2048_06}}"

// Instantiate the material providers library
matProv, err := mpl.NewClient(mpltypes.MaterialProvidersConfig{})
if err != nil {
    panic(err)
}

// Create Raw RSA keyring
rsaKeyRingInput := mpltypes.CreateRawRsaKeyringInput{
    KeyName:       keyName,
    KeyNamespace:  keyNamespace,
    PaddingScheme: mpltypes.{{PaddingSchemeOaepSha512Mgf1}},
    PublicKey:     ({{RSAPublicKey}}),
    PrivateKey:    ({{RSAPrivateKey}}),
}
rsaKeyring, err := matProv.CreateRawRsaKeyring(context.Background(), rsaKeyRingInput)
if err != nil {
    panic(err)
}
```

------