Encrypting and decrypting jenkins credentials

Encrypting and decrypting jenkins credentials - security

Published on: 2020-04-28

Word count: 491

Estimated reading time: 3 minutes

Jenkins uses AES-128-ECB to encrypt and decrypt secrets.
Each jenkins instance generates an encryption key on first-start. This key is used to encrypt and decrypt secrets. It is commonly named master.key.

More details can be found in Secret`s JavaDoc.

When using the Web-UI, jenkins automatically encrypt and decrypt secrets. However, when using JCasC (Jenkins Configuration-as-Code) or just out of interest, we can manually en- and decrypt secrets.

Open Script Console

First of all, we need to open the Script Console.

  1. Open your jenkins instance
  2. Click on Manage Jenkins Manage Jenkins
  3. Find the Script Console Find Script Console
  4. You should see the Script Console now: Script Console

The Script Console provides us with a basic Groovy interpreter, coupled with some Jenkins libraries.

Encrypting a secret

Put the following code into the script console and hit Run:

import hudson.util.Secret

def secret = Secret.fromString("MySuperSecretPassword")
println(secret.getEncryptedValue())

First, we import hudson.util.Secret which gives us access to the Secret class. Calling Secret::fromString(String) checks the string we entered and if it detects an encrypted secret, it will initialize as decryptable, otherwise as encryptable.

In this case: MySuperSecretPassword is not an encoded secret, thus it’s encryptable.

Calling Secret::getEncryptedValue() returns us another string: The encrypted secret.

Finally, we use println(String) to output/print the secret.
For example, it yields for me {AQAAABAAAAAgfYagUACnp****/1ZLqYcfvLvnQrb9WqxVd****/oRvE5BoAQVE+Xihpqc0Zr****}.

Note: Since each jenkins instance generates their own encryption key each secret generated by me will be different from yours, even though you entered the same non encoded secret.
For security reasons I changed my output slightly.

Decrypting a secret

Put the following code into the script console and hit Run:

import hudson.util.Secret

def secret = Secret.fromString("{AQAAABAAAAAgfYagUACnp****/1ZLqYcfvLvnQrb9WqxVd****/oRvE5BoAQVE+Xihpqc0Zr****}")
println(secret.getPlainText())

First, we import hudson.util.Secret which gives us access to the Secret class. Calling Secret::fromString(String) checks the string we entered and if it detects an encrypted secret, it will initialize as decryptable, otherwise as encryptable.

In this case: {AQAAABAAAAAgfYagUACnp****/1ZLqYcfvLvnQrb9WqxVd****/oRvE5BoAQVE+Xihpqc0Zr****} is an encoded secret, thus it’s decryptable.

Calling Secret::getPlainText() returns us another string: The decrypted secret.

Finally, we use println(String) to output/print the secret.
For example, it yields for me MySuperSecretPassword.

Note: Since each jenkins instance generates their own encryption key each secret generated by me will be different from yours, even though you entered the same non encoded secret.
For security reasons I changed my input slightly.

Final note

When entering the encrypted secret, for example {AQAAABAAAAAgfYagUACnp****/1ZLqYcfvLvnQrb9WqxVd****/oRvE5BoAQVE+Xihpqc0Zr****}, and calling Secret::getEncryptedValue() again, it will give back our input: {AQAAABAAAAAgfYagUACnp****/1ZLqYcfvLvnQrb9WqxVd****/oRvE5BoAQVE+Xihpqc0Zr****}.
This is because Secret::fromString(String) detects rather the input is an encrypted or decrypted secret as mentioned above.