brief introduction
RSA asymmetric encryption has very strong security. HTTPS's SSL encryption uses this method to encrypt HTTPS requests. RSA algorithm is called asymmetric encryption because it involves Private Key and Public Key, which are used for encryption and decryption respectively. Private Key and Public Key are interoperable, i.e. those encrypted with private key can be decrypted with public key, and those encrypted with public key can be decrypted with private key. Traditional one-way authentication only uses public key to encrypt, and only the party with private key can decrypt. For example, a web server would have a pair of private keys and public keys. The browser client holds the public key of the server. When the client needs to send data to the server, it encrypts it with the public key of the server, and decrypts it with the private key when the server receives the data. When the client verifies that the server is a real server, it compares the public key provided by the server with the public key saved locally, so that the authenticity of the server can be verified.
In our config server, RSA algorithm can be used for data encryption and decryption.
Project source code
Generate test Keystore
We need to use jdk's own keytool tool tool to generate a keystore with private key information stored in it, using the following command line:
keytool -genkeypair -alias config-server-key -keyalg RSA -dname "CN=Config Server,OU=Xuqian,O=My Own Company,L=Beijing,S=Beijing,C=CN" -keypass changeit -keystore server.jks -storepass changeit
The - genkeypair parameter produces a pair of public key s and private key s. - alias specifies an alias for key to distinguish different keys in the same keystore. - keyalg specifies the algorithm for generating keys, where the default RSA is used - dname specifies common name, or CN, to verify the identity of key. Each of them is a custom parameter. OU is the unit name, O is the organization name, L is the city, S is the province/state, C is the country. -keypass is the key password - keystore is the file name of keystore - storepass access keystore password
The privte key s generated by the above tools are stored in a key store named server.jks. So far, we have only produced private key. Spring Cloud Config Server generates a public key with the program according to the key information provided by us. Refer to the source code org. spring framework. security. rsa. crypto. KeyStoreKey Factory as follows:
public KeyPair getKeyPair(String alias, char[] password) { try { synchronized (lock) { if (store == null) { synchronized (lock) { // Get an instance object of keystore based on the keystore file address and password provided by the configuration store = KeyStore.getInstance("jks"); store.load(resource.getInputStream(), this.password); } } } // Get private key from keystore according to alias and password provided by configuration RSAPrivateCrtKey key = (RSAPrivateCrtKey) store.getKey(alias, password); // Define Public Key Generation Rules RSAPublicKeySpec spec = new RSAPublicKeySpec(key.getModulus(), key.getPublicExponent()); // Generating Public Key PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(spec); return new KeyPair(publicKey, key); } catch (Exception e) { throw new IllegalStateException("Cannot load keys from store: " + resource, e); } }
The Java Security API is used here to operate on key s. See Notes. The information above is then provided through the bootstrap.xml configuration file in configserver:
encrypt: #key: Thisismysecretkey key-store: location: file://${user.home}/development/keys/server.jks password: changeit alias: config-server-key secret: changeit
Because we can't use symmetric encryption and asymmetric encryption at the same time, we annotate the encrypt.key configuration and specify the parameters of asymmetric encryption:
- location: Keystore file path
- Password: keystore password
- Alias: alias: key
- secret:key password
test
We continue to encrypt a test data using the encrypt API:
curl http://localhost:8888/encrypt -d 23456789
Returns the encrypted character:
AQAPWOUOh4WVexGgVv+bgtKc5E0d5Aba8VUKnzEXh27HyKSAbW+wyzDwZTbk5QYfXpoCAs413rdeNIdR2ez44nkjT5V+438/VQExySzjZPhP0xYXi9YIaJqA3+Ji+IWK8hrGtJ4dzxIkmItiimCOirLdZzZGDm/yklMUVh7lARSNuMxXGKlpdBPKYWdqHm57ob6Sb0ivm4H4mL1n4d3QUCuE7hh2F4Aw4oln7XueyMkRPTtPy8OpnBEEZhRfmaL/auVZquLU5jjMNJk9JiWOy+DSTscViY/MZ+dypv6F4AfDdVvog89sNmPzcUT+zmB8jXHdjLoKy+63RG326WffY9OPuImW6/kCWZHV6Vws55hHqRy713W6yDBlrQ/gYC3Wils=
Then test decryption
curl http://localhost:8888/decrypt -d AQAPWOUOh4+bgtKc5E0d5Aba8VUKnzEXh27HyKSAbW+wyzDwZTbk5QYfXpoCAs413rdeNIdR2ez44nkjT5V+438/VQExySzjZPhP0xYXi9YIaJqA3+Ji+IWK8hrGtJ4dzxIkmItiimCOirLdZzZGDm/yklMUVh7lARSNuMxXGKlpdBPKYWdqHm57ob6Sb0ivm4H4mL1n4d3QUCuE7hh2F4Aw4oln7XueyMkRPTtPy8OpnBEEZhRfmaL/auVZquLU5jjMNJk9JiWOy+DSTscViY/MZ+dypv6F4AfDdVvog89sNmPzcUT+zmB8jXHdjLoKy+63RG326WffY9OPuImW6/kCWZHV6Vws55hHqRy713W6yDBlrQ/gYC3Wils=
Will return
23456789
We can also modify web-client.yml to verify that:
#test: #password: '{cipher}94c1027141add9844ec47f0be13caebb6b38ed1dcf99811b1a5cd2b874c64407' user: password: '{cipher}AQAPWOUOh4WVexGgVv+bgtKc5E0d5Aba8VUKnzEXh27HyKSAbW+wyzDwZTbk5QYfXpoCAs413rdeNIdR2ez44nkjT5V+438/VQExySzjZPhP0xYXi9YIaJqA3+Ji+IWK8hrGtJ4dzxIkmItiimCOirLdZzZGDm/yklMUVh7lARSNuMxXGKlpdBPKYWdqHm57ob6Sb0ivm4H4mL1n4d3QUCuE7hh2F4Aw4oln7XueyMkRPTtPy8OpnBEEZhRfmaL/auVZquLU5jjMNJk9JiWOy+DSTscViY/MZ+dypv6F4AfDdVvog89sNmPzcUT+zmB8jXHdjLoKy+63RG326WffY9OPuImW6/kCWZHV6Vws55hHqRy713W6yDBlrQ/gYC3Wils='
Remark test.password and add a new user.password to use the encrypted configuration value. Then submit the gitee repository and access the configuration file through url:
http://localhost:8888/web-client/default
The following results are obtained:
{ "name": "web-client", "profiles": [ "default" ], "label": null, "version": "3044a5345fb86d09a043ca7404b9e57c8c13c512", "state": null, "propertySources": [ { "name": "https://gitee.com/zxuqian/spring-cloud-config-remote/web-client.yml", "source": { "message": "This message comes from the remote configuration repository", "management.endpoints.web.exposure.include": "*", "user.password": "23456789" } } ] }