美文网首页
jenkins凭证解密

jenkins凭证解密

作者: 修罗大人 | 来源:发表于2020-04-22 09:40 被阅读0次

由于某种原因,我们需要对jenkins存储的凭证进行解密.

我们需要使用三个文件,分别是

  1. secrets目录下的master.key
  2. secrets目录下的hudson.util.Secret
  3. home目录下的credentials.xml,这里存储了密文密码,如下
<com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>
  <scope>GLOBAL</scope>
  <id>xxx</id>
  <description>xxxx</description>
  <username>xxx</username>
  <password>密文密码</password>
</com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl>

其中,password 里的用{}包裹的就是我们要用的,把大括号一起复制到下面代码里

代码如下,使用了依赖

      <dependency>
          <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
package com.xiuluo.test.jenkins;

import org.apache.commons.io.IOUtils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;

import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * 文件名称:Test<br>
 * 初始作者:修罗大人<br>
 * 创建日期:2020-04-21 14:28<br>
 * 功能说明:<br>
 * <br>
 */
public class Test {

    private static final String KEY_ALGORITHM = "AES";
    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
    private final String rootDir = "secrets文件夹路径";
    private static final byte[] MAGIC = "::::MAGIC::::".getBytes();
    // 密文密码
    private static final String data = "密文密码";


    @org.junit.Test
    public void decrypt() {

        byte[] payload;
        try {
            payload = Base64.getDecoder().decode(data.substring(1, data.length()-1));
        } catch (IllegalArgumentException e) {
            return;
        }
        switch (payload[0]) {
            case 1:
                // For PAYLOAD_V1 we use this byte shifting model, V2 probably will need DataOutput
                int ivLength = ((payload[1] & 0xff) << 24)
                        | ((payload[2] & 0xff) << 16)
                        | ((payload[3] & 0xff) << 8)
                        | (payload[4] & 0xff);
                int dataLength = ((payload[5] & 0xff) << 24)
                        | ((payload[6] & 0xff) << 16)
                        | ((payload[7] & 0xff) << 8)
                        | (payload[8] & 0xff);
                if (payload.length != 1 + 8 + ivLength + dataLength) {
                    // not valid v1
                    return;
                }
                byte[] iv = Arrays.copyOfRange(payload, 9, 9 + ivLength);
                byte[] code = Arrays.copyOfRange(payload, 9+ivLength, payload.length);
                String text;
                try {
                    text = new String(decrypt(iv).doFinal(code), UTF_8);
                    System.out.println("密码明文:" + text);
                } catch (GeneralSecurityException e) {
                    // it's v1 which cannot be historical, but not decrypting
                    return;
                }
//                return new Secret(text, iv);
            default:
                return;
        }

    }

    public Cipher decrypt(byte[] iv) {
        try {
            Cipher cipher = getCipher(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, getKey(), new IvParameterSpec(iv));
            return cipher;
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }

    private synchronized SecretKey getKey() throws Exception {
        SecretKey secret  = null;
            try {
                byte[] payload = load();
                if (payload == null) {
                    payload = randomBytes(256);
//                    store(payload);
                }
                // Due to the stupid US export restriction JDK only ships 128bit version.
                secret = new SecretKeySpec(payload, 0, 128 / 8, KEY_ALGORITHM);
            } catch (IOException e) {
                throw e;
            }
        return secret;
    }

    protected byte[] load() throws Exception {
        try {
            File f = new File(rootDir,"hudson.util.Secret");
            if (!f.exists())    return null;

            Cipher sym = getCipher("AES");
            sym.init(Cipher.DECRYPT_MODE, getMasterKey());
            try (InputStream fis= Files.newInputStream(f.toPath());
                 CipherInputStream cis = new CipherInputStream(fis, sym)) {
                byte[] bytes = IOUtils.toByteArray(cis);
                return verifyMagic(bytes);
            }
        } catch (Exception x) {
            if (x.getCause() instanceof BadPaddingException) {
                throw x; // broken somehow
            } else {
                throw x;
            }
        }
    }

    public static Cipher getCipher(String algorithm) throws GeneralSecurityException {
        return Cipher.getInstance(algorithm);
    }

    private SecretKey getMasterKey() throws Exception {
        File file = new File(rootDir,"master.key");
        SecretKey masterKey = toAes128Key(read(file).trim());

        return masterKey;
    }

    public String read(File file) throws Exception {
        StringWriter out = new StringWriter();
        PrintWriter w = new PrintWriter(out);
        BufferedReader in = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8);
        String line;
        while ((line = in.readLine()) != null)
            w.println(line);
        return out.toString();
    }

    public byte[] randomBytes(int size) {
        byte[] random = new byte[size];
        new SecureRandom().nextBytes(random);
        return random;
    }

    private byte[] verifyMagic(byte[] payload) {
        int payloadLen = payload.length-MAGIC.length;
        if (payloadLen<0)   return null;    // obviously broken

        for (int i=0; i<MAGIC.length; i++) {
            if (payload[payloadLen+i]!=MAGIC[i])
                return null;    // broken
        }
        byte[] truncated = new byte[payloadLen];
        System.arraycopy(payload,0,truncated,0,truncated.length);
        return truncated;
    }

    public static String toHexString(byte[] bytes) {
        int start = 0;
        int len = bytes.length;

        StringBuilder buf = new StringBuilder();
        for( int i=0; i<len; i++ ) {
            int b = bytes[start+i]&0xFF;
            if(b<16)    buf.append('0');
            buf.append(Integer.toHexString(b));
        }
        return buf.toString();
    }

    public static SecretKey toAes128Key(String s) {
        try {
            // turn secretKey into 256 bit hash
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            digest.reset();
            digest.update(s.getBytes(StandardCharsets.UTF_8));

            // Due to the stupid US export restriction JDK only ships 128bit version.
            return new SecretKeySpec(digest.digest(),0,128/8, "AES");
        } catch (NoSuchAlgorithmException e) {
            throw new Error(e);
        }
    }

}

相关文章

  • jenkins凭证解密

    由于某种原因,我们需要对jenkins存储的凭证进行解密. 我们需要使用三个文件,分别是 secrets目录下的m...

  • jenkins配置凭证

    一、配置gitlab凭证 1、jenkins 插件准备 系统管理->插件管理 :GitLab ,Publish O...

  • Jenkins 处理凭证

    Secret 文本,带密码的用户名,Secret 文件 Jenkins 的声明式流水线语法有一个 credenti...

  • Jenkins:凭证管理

    凭据可以用来存储需要密文保护的数据库密码、Gitlab密码、Docker私有仓库密码等等,以便Jenkins可以和...

  • mimikatz 解密RDP凭证

    1.查询本地保存的RDP凭证 cmdkey /l 2.获取RDP本地保存凭证的文件 dir /a %userpro...

  • jenkins 凭证(Credentials)修改

    Jenkins是一个开源软件项目,是基于Java开发的一种[持续集成]工具,用于监控持续重复的工作,旨在提供一个开...

  • Jenkins2 学习系列18 -- 凭证管理

    凭证 Credentials 凭证可以是一段字符串如密码,私钥文件等,是Jenkins进行受限操作时的凭据。比如S...

  • Jenkins实践指南-08-Jenkins 凭证管理

    4. Jenkins 凭证管理     随着网络环境的变化,如果在Jenkins中使用明文密码会造成一些安全隐患。...

  • Jenkins(三) Jenkins用户管理及凭证

    用户管理 我们可以利用Role-based Authorization Strategy 插件来管理Jenkins...

  • DevOps

    1、jenkins pipeline从git下载代码执行sonarqube扫描 2、使用凭证中的用户名密码 1、p...

网友评论

      本文标题:jenkins凭证解密

      本文链接:https://www.haomeiwen.com/subject/zkebihtx.html