快速入门:加密技术

开始使用 Dapr 加密构建块

我们来了解一下 Dapr 的加密构建块。在这个快速入门中,您将创建一个应用程序,使用 Dapr 加密 API 来加密和解密数据。您将:

  • 加密并解密一个短字符串(使用 RSA 密钥),在内存中读取结果,使用 Go 的字节切片格式。
  • 加密并解密一个大文件(使用 AES 密钥),通过流的方式将加密和解密的数据存储到文件中。

目前,您可以使用 Go SDK 体验加密 API。


此快速入门包括一个名为 crypto-quickstart 的 JavaScript 应用程序。

前置条件

对于此示例,您将需要:

步骤 1:设置环境

克隆 快速入门仓库中提供的示例

git clone https://github.com/dapr/quickstarts.git

在终端中,从根目录导航到加密示例。

cd cryptography/javascript/sdk

导航到包含源代码的文件夹:

cd ./crypto-quickstart

安装依赖项:

npm install

步骤 2:使用 Dapr 运行应用程序

应用程序代码定义了两个必需的密钥:

  • 私有 RSA 密钥
  • 一个 256 位对称(AES)密钥

使用 OpenSSL 生成两个密钥:一个 RSA 密钥和一个 AES 密钥,并将它们写入两个文件:

mkdir -p keys
# 生成一个私有 RSA 密钥,4096 位密钥
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out keys/rsa-private-key.pem
# 为 AES 生成一个 256 位密钥
openssl rand -out keys/symmetric-key-256 32

使用 Dapr 运行 Go 服务应用程序:

dapr run --app-id crypto-quickstart --resources-path ../../../components/ -- npm start

预期输出

== APP == 2023-10-25T14:30:50.435Z INFO [GRPCClient, GRPCClient] Opening connection to 127.0.0.1:58173
== APP == == Encrypting message using buffers
== APP == Encrypted the message, got 856 bytes
== APP == == Decrypting message using buffers
== APP == Decrypted the message, got 24 bytes
== APP == The secret is "passw0rd"
== APP == == Encrypting message using streams
== APP == Encrypting federico-di-dio-photography-Q4g0Q-eVVEg-unsplash.jpg to encrypted.out
== APP == Encrypted the message to encrypted.out
== APP == == Decrypting message using streams
== APP == Decrypting encrypted.out to decrypted.out.jpg
== APP == Decrypted the message to decrypted.out.jpg

发生了什么?

local-storage.yaml

之前,您在 crypto-quickstarts 中创建了一个名为 keys 的目录。在 local-storage 组件 YAML 中,path 元数据映射到新创建的 keys 目录。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: localstorage
spec:
  type: crypto.dapr.localstorage
  version: v1
  metadata:
    - name: path
      # 路径相对于示例所在的文件夹
      value: ./keys

index.mjs

应用程序文件 使用您生成的 RSA 和 AES 密钥加密和解密消息和文件。应用程序创建了一个新的 Dapr SDK 客户端:

async function start() {
  const client = new DaprClient({
    daprHost,
    daprPort,
    communicationProtocol: CommunicationProtocolEnum.GRPC,
  });

  // 从缓冲区加密和解密消息
  await encryptDecryptBuffer(client);

  // 使用流加密和解密消息
  await encryptDecryptStream(client);
}
使用 RSA 密钥加密和解密字符串

一旦创建了客户端,应用程序就会加密一条消息:

async function encryptDecryptBuffer(client) {
  // 要加密的消息
  const plaintext = `The secret is "passw0rd"`

  // 首先,加密消息
  console.log("== Encrypting message using buffers");

  const encrypted = await client.crypto.encrypt(plaintext, {
    componentName: "localstorage",
    keyName: "rsa-private-key.pem",
    keyWrapAlgorithm: "RSA",
  });

  console.log("Encrypted the message, got", encrypted.length, "bytes");

然后应用程序解密消息:

  // 解密消息
  console.log("== Decrypting message using buffers");
  const decrypted = await client.crypto.decrypt(encrypted, {
    componentName: "localstorage",
  });

  console.log("Decrypted the message, got", decrypted.length, "bytes");
  console.log(decrypted.toString("utf8"));

  // ...
}
使用 AES 密钥加密和解密大文件

接下来,应用程序加密一个大图像文件:

async function encryptDecryptStream(client) {
  // 首先,加密消息
  console.log("== Encrypting message using streams");
  console.log("Encrypting", testFileName, "to encrypted.out");

  await pipeline(
    createReadStream(testFileName),
    await client.crypto.encrypt({
      componentName: "localstorage",
      keyName: "symmetric-key-256",
      keyWrapAlgorithm: "A256KW",
    }),
    createWriteStream("encrypted.out"),
  );

  console.log("Encrypted the message to encrypted.out");

然后应用程序解密大图像文件:

  // 解密消息
  console.log("== Decrypting message using streams");
  console.log("Decrypting encrypted.out to decrypted.out.jpg");
  await pipeline(
    createReadStream("encrypted.out"),
    await client.crypto.decrypt({
      componentName: "localstorage",
    }),
    createWriteStream("decrypted.out.jpg"),
  );

  console.log("Decrypted the message to decrypted.out.jpg");
}

此快速入门包括一个名为 crypto-quickstart 的 Go 应用程序。

前置条件

对于此示例,您将需要:

步骤 1:设置环境

克隆 快速入门仓库中提供的示例

git clone https://github.com/dapr/quickstarts.git

在终端中,从根目录导航到加密示例。

cd cryptography/go/sdk

步骤 2:使用 Dapr 运行应用程序

导航到包含源代码的文件夹:

cd ./crypto-quickstart

应用程序代码定义了两个必需的密钥:

  • 私有 RSA 密钥
  • 一个 256 位对称(AES)密钥

使用 OpenSSL 生成两个密钥:一个 RSA 密钥和一个 AES 密钥,并将它们写入两个文件:

mkdir -p keys
# 生成一个私有 RSA 密钥,4096 位密钥
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out keys/rsa-private-key.pem
# 为 AES 生成一个 256 位密钥
openssl rand -out keys/symmetric-key-256 32

使用 Dapr 运行 Go 服务应用程序:

dapr run --app-id crypto-quickstart --resources-path ../../../components/ -- go run .

预期输出

== APP == dapr client initializing for: 127.0.0.1:52407
== APP == Encrypted the message, got 856 bytes
== APP == Decrypted the message, got 24 bytes
== APP == The secret is "passw0rd"
== APP == Wrote decrypted data to encrypted.out
== APP == Wrote decrypted data to decrypted.out.jpg

发生了什么?

local-storage.yaml

之前,您在 crypto-quickstarts 中创建了一个名为 keys 的目录。在 local-storage 组件 YAML 中,path 元数据映射到新创建的 keys 目录。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: localstorage
spec:
  type: crypto.dapr.localstorage
  version: v1
  metadata:
    - name: path
      # 路径相对于示例所在的文件夹
      value: ./keys

app.go

应用程序文件 使用您生成的 RSA 和 AES 密钥加密和解密消息和文件。应用程序创建了一个新的 Dapr SDK 客户端:

func main() {
	// 创建一个新的 Dapr SDK 客户端
	client, err := dapr.NewClient()
    
    //...

	// 步骤 1:使用 RSA 密钥加密字符串,然后解密并在终端中显示输出
	encryptDecryptString(client)

	// 步骤 2:加密大文件,然后使用 AES 密钥解密
	encryptDecryptFile(client)
}
使用 RSA 密钥加密和解密字符串

一旦创建了客户端,应用程序就会加密一条消息:

func encryptDecryptString(client dapr.Client) {
    // ...

	// 加密消息
	encStream, err := client.Encrypt(context.Background(),
		strings.NewReader(message),
		dapr.EncryptOptions{
			ComponentName: CryptoComponentName,
			// 要使用的密钥名称
			// 由于这是一个 RSA 密钥,我们将其指定为密钥包装算法
			KeyName:          RSAKeyName,
			KeyWrapAlgorithm: "RSA",
		},
	)

    // ...

	// 该方法返回一个可读流,我们在内存中完整读取
	encBytes, err := io.ReadAll(encStream)
    // ...

	fmt.Printf("Encrypted the message, got %d bytes\n", len(encBytes))

然后应用程序解密消息:

	// 现在,解密加密的数据
	decStream, err := client.Decrypt(context.Background(),
		bytes.NewReader(encBytes),
		dapr.DecryptOptions{
			// 我们只需要传递组件的名称
			ComponentName: CryptoComponentName,
			// 传递密钥名称是可选的
			KeyName: RSAKeyName,
		},
	)

    // ...

	// 该方法返回一个可读流,我们在内存中完整读取
	decBytes, err := io.ReadAll(decStream)

    // ...

	// 在控制台上打印消息
	fmt.Printf("Decrypted the message, got %d bytes\n", len(decBytes))
	fmt.Println(string(decBytes))
}
使用 AES 密钥加密和解密大文件

接下来,应用程序加密一个大图像文件:

func encryptDecryptFile(client dapr.Client) {
	const fileName = "liuguangxi-66ouBTTs_x0-unsplash.jpg"

	// 获取输入文件的可读流
	plaintextF, err := os.Open(fileName)

    // ...

	defer plaintextF.Close()

	// 加密文件
	encStream, err := client.Encrypt(context.Background(),
		plaintextF,
		dapr.EncryptOptions{
			ComponentName: CryptoComponentName,
			// 要使用的密钥名称
			// 由于这是一个对称密钥,我们将 AES 指定为密钥包装算法
			KeyName:          SymmetricKeyName,
			KeyWrapAlgorithm: "AES",
		},
	)

    // ...

	// 将加密数据写入文件 "encrypted.out"
	encryptedF, err := os.Create("encrypted.out")

    // ...

	encryptedF.Close()

	fmt.Println("Wrote decrypted data to encrypted.out")

然后应用程序解密大图像文件:

	// 现在,解密加密的数据
	// 首先,再次打开文件 "encrypted.out",这次用于读取
	encryptedF, err = os.Open("encrypted.out")

    // ...

	defer encryptedF.Close()

	// 现在,解密加密的数据
	decStream, err := client.Decrypt(context.Background(),
		encryptedF,
		dapr.DecryptOptions{
			// 我们只需要传递组件的名称
			ComponentName: CryptoComponentName,
			// 传递密钥名称是可选的
			KeyName: SymmetricKeyName,
		},
	)

    // ...

	// 将解密数据写入文件 "decrypted.out.jpg"
	decryptedF, err := os.Create("decrypted.out.jpg")

    // ...

	decryptedF.Close()

	fmt.Println("Wrote decrypted data to decrypted.out.jpg")
}

观看演示

观看此 Dapr 社区电话 #83 中的加密 API 演示视频

告诉我们您的想法!

我们正在不断努力改进我们的快速入门示例,并重视您的反馈。您觉得这个快速入门有帮助吗?您有改进建议吗?

加入我们的 discord 频道进行讨论。

下一步

探索 Dapr 教程 >>