Encryption and Decryption

要使用加密和解密功能,您需要在 JVM 中安装全功能 JCE(默认情况下不包含在内)。您可以从 Oracle 下载 “Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files” 并按照安装说明进行操作(基本上,您需要使用下载的文件替换 JRE lib/security 目录中的两个策略文件)。

To use the encryption and decryption features you need the full-strength JCE installed in your JVM (it is not included by default). You can download the “Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files” from Oracle and follow the installation instructions (essentially, you need to replace the two policy files in the JRE lib/security directory with the ones that you downloaded).

如果远程属性源包含加密内容(以 {cipher} 开头),在通过 HTTP 发送给客户端之前,它们会先进行解密。此设置的主要优点是当属性值处于“静止状态”(例如,在 git 仓库中时)时,不必以纯文本形式提供。如果无法解密值,则会将其从属性源中删除,并添加一个附加的属性,该属性具有相同的键,但带有 invalid 前缀,值表示“不适用”(通常为 <n/a>)。这在很大程度上是为了防止密文被用作密码并且意外泄露。

If the remote property sources contain encrypted content (values starting with {cipher}), they are decrypted before sending to clients over HTTP. The main advantage of this setup is that the property values need not be in plain text when they are “at rest” (for example, in a git repository). If a value cannot be decrypted, it is removed from the property source and an additional property is added with the same key but prefixed with invalid and a value that means “not applicable” (usually <n/a>). This is largely to prevent cipher text being used as a password and accidentally leaking.

如果您为配置客户端应用程序设置远程配置仓库,则其中可能包含类似于以下内容的 application.yml

If you set up a remote config repository for config client applications, it might contain an application.yml similar to the following:

application.yml
spring:
  datasource:
    username: dbuser
    password: '{cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ'

application.properties 文件中的加密值不得用引号引起来。否则,该值不会被解密。以下示例展示了可用的值:

Encrypted values in application.properties file must not be wrapped in quotes. Otherwise, the value is not decrypted. The following example shows values that would work:

application.properties
spring.datasource.username: dbuser
spring.datasource.password: {cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ

您可以安全地将此纯文本推送到共享 git 仓库中,并且秘密密码仍受保护。

You can safely push this plain text to a shared git repository, and the secret password remains protected.

该服务器还公开 /encrypt/decrypt 端点(假设这些端点是安全的,并且仅由经过授权的代理程序访问)。如果您编辑远程配置文件,您可以使用 Config Server 通过对 /encrypt 端点 POST,来加密值,如下例所示:

The server also exposes /encrypt and /decrypt endpoints (on the assumption that these are secured and only accessed by authorized agents). If you edit a remote config file, you can use the Config Server to encrypt values by POSTing to the /encrypt endpoint, as shown in the following example:

$ curl localhost:8888/encrypt -s -d mysecret
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda

如果您正在使用 curl 进行测试,请使用 --data-urlencode(而不是 -d)并使用 = 为要加密的值添加前缀(curl 需要这样做)或设置一个明确的 Content-Type: text/plain 以确保在有特殊字符('+' 特别棘手)时 curl 正确对数据进行编码。

If you are testing with curl, then use --data-urlencode (instead of -d) and prefix the value to encrypt with = (curl requires this) or set an explicit Content-Type: text/plain to make sure curl encodes the data correctly when there are special characters ('+' is particularly tricky).

请确保不要在加密值中包含任何 curl 命令统计信息,这就是这些示例使用 -s 选项使它们静音的原因。将值输出到文件有助于避免此问题。

Be sure not to include any of the curl command statistics in the encrypted value, this is why the examples use the -s option to silence them. Outputting the value to a file can help avoid this problem.

逆操作也可以通过 /decrypt 获得(如果服务器使用对称密钥或完整密钥对进行了配置),如下例所示:

The inverse operation is also available through /decrypt (provided the server is configured with a symmetric key or a full key pair), as shown in the following example:

$ curl localhost:8888/decrypt -s -d 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret

获取加密值并在将其放入 YAML 或属性文件前添加 {cipher} 前缀,然后提交并将其推送到远程(可能不安全)存储中。

Take the encrypted value and add the {cipher} prefix before you put it in the YAML or properties file and before you commit and push it to a remote (potentially insecure) store.

/encrypt/decrypt 端点也都接受 /*/{application}/{profiles} 形式的路径,当客户端调用主环境资源时,该路径可用于按每个应用程序(名称)和每个配置文件控制加密。

The /encrypt and /decrypt endpoints also both accept paths in the form of /*/{application}/{profiles}, which can be used to control cryptography on a per-application (name) and per-profile basis when clients call into the main environment resource.

要以这种粒度控制密码学,您还必须提供一个类型为 TextEncryptorLocator@Bean,它为每个名称和配置文件创建不同的加密器。默认提供的那个不会这样做(所有加密都使用相同的密钥)。

To control the cryptography in this granular way, you must also provide a @Bean of type TextEncryptorLocator that creates a different encryptor per name and profiles. The one that is provided by default does not do so (all encryptions use the same key).

spring 命令行客户端(安装了 Spring Cloud CLI 扩展)也可用于加密和解密,如下例所示:

The spring command line client (with Spring Cloud CLI extensions installed) can also be used to encrypt and decrypt, as shown in the following example:

$ spring encrypt mysecret --key foo
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
$ spring decrypt --key foo 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret

要使用文件中的密钥(比如用于加密的 RSA 公钥),请用“@”前缀密钥值并提供文件路径,如下面的示例所示:

To use a key in a file (such as an RSA public key for encryption), prepend the key value with "@" and provide the file path, as shown in the following example:

$ spring encrypt mysecret --key @${HOME}/.ssh/id_rsa.pub
AQAjPgt3eFZQXwt8tsHAVv/QHiY5sI2dRcR+...

--key 参数是强制性的(尽管带有 -- 前缀)。

The --key argument is mandatory (despite having a -- prefix).