工具类修改
This commit is contained in:
parent
dc4ca13ef0
commit
04674b2d7c
@ -38,10 +38,16 @@
|
|||||||
<groupId>com.jcraft</groupId>
|
<groupId>com.jcraft</groupId>
|
||||||
<artifactId>jsch</artifactId>
|
<artifactId>jsch</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>com.antherd</groupId>-->
|
||||||
|
<!-- <artifactId>sm-crypto</artifactId>-->
|
||||||
|
<!-- <version>0.3.2</version>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
<!-- 上面的依赖与java17有冲突-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.antherd</groupId>
|
<groupId>org.bouncycastle</groupId>
|
||||||
<artifactId>sm-crypto</artifactId>
|
<artifactId>bcprov-jdk18on</artifactId>
|
||||||
<version>0.3.2</version>
|
<version>1.80</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.hierynomus</groupId>
|
<groupId>com.hierynomus</groupId>
|
||||||
|
@ -71,6 +71,7 @@ public class DefaultWorkerManager extends WorkerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("================WorkerManager初始化完毕");
|
log.info("================WorkerManager初始化完毕");
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,7 +26,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
//@Plugin(taskType = "CUSTOM_IMAGE_EXECUTION_COMMAND")
|
//@Plugin(taskType = "CUSTOM_IMAGE_EXECUTION_COMMAND")
|
||||||
//@Plugin(taskType = "test")
|
@Plugin(taskType = "testSSH")
|
||||||
public class DIYImageExecuteCommandWorker extends SshWorker {
|
public class DIYImageExecuteCommandWorker extends SshWorker {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -60,7 +60,7 @@ public class DIYImageExecuteCommandWorker extends SshWorker {
|
|||||||
|
|
||||||
//获取机器
|
//获取机器
|
||||||
MachineInfo machineInfoDO = this.getMachineInfoService().getById(machineId);
|
MachineInfo machineInfoDO = this.getMachineInfoService().getById(machineId);
|
||||||
statusCode = shell(machineInfoDO,taskLog,
|
statusCode = shell(machineInfoDO,"1qaz!QAZ",taskLog,
|
||||||
"echo \"自定义镜像执行命令\"",
|
"echo \"自定义镜像执行命令\"",
|
||||||
commandScript
|
commandScript
|
||||||
);
|
);
|
||||||
|
@ -22,7 +22,7 @@ public abstract class SshWorker extends BaseWorker{
|
|||||||
* @param commands 命令
|
* @param commands 命令
|
||||||
* @return 0 成功;其他值 失败
|
* @return 0 成功;其他值 失败
|
||||||
*/
|
*/
|
||||||
public int shell(MachineInfo machineInfo, PipTaskLog taskLog, String... commands) {
|
public int shell(MachineInfo machineInfo,String sudoPassword, PipTaskLog taskLog, String... commands) {
|
||||||
List<String> commandList = Arrays.asList(commands);
|
List<String> commandList = Arrays.asList(commands);
|
||||||
if(MachineSystemEnum.WINDOWS.getSystem().equals(machineInfo.getOsSystem())){
|
if(MachineSystemEnum.WINDOWS.getSystem().equals(machineInfo.getOsSystem())){
|
||||||
return powerShell(machineInfo, commandList);
|
return powerShell(machineInfo, commandList);
|
||||||
@ -38,7 +38,7 @@ public abstract class SshWorker extends BaseWorker{
|
|||||||
//执行命令,并且把命令的执行回传到前端
|
//执行命令,并且把命令的执行回传到前端
|
||||||
// TODO 记录日志
|
// TODO 记录日志
|
||||||
// loggerService.sendMessage(key, var);
|
// loggerService.sendMessage(key, var);
|
||||||
statusCode = ssh.execNew(commandList, taskLog::append);
|
statusCode = ssh.execNew(commandList,sudoPassword, taskLog::append);
|
||||||
log.info("exit-status: " + statusCode);
|
log.info("exit-status: " + statusCode);
|
||||||
//主动释放当前socket连接
|
//主动释放当前socket连接
|
||||||
// loggerService.close(key);
|
// loggerService.close(key);
|
||||||
|
@ -28,7 +28,7 @@ public interface SshClient {
|
|||||||
* @return 执行成功返回0,失败返回1
|
* @return 执行成功返回0,失败返回1
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
int execNew(List<String> commands, ExecCallback execCallback) throws IOException;
|
int execNew(List<String> commands,String sudoPassword, ExecCallback execCallback) throws IOException;
|
||||||
/**
|
/**
|
||||||
* 执行ssh 命令
|
* 执行ssh 命令
|
||||||
*
|
*
|
||||||
|
@ -158,16 +158,15 @@ public class SshCommand implements SshClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int execNew(List<String> commands, ExecCallback execCallback) throws IOException {
|
public int execNew(List<String> commands, String sudoPassword, ExecCallback execCallback) throws IOException {
|
||||||
|
|
||||||
ChannelShell channel = null;
|
ChannelShell channel = null;
|
||||||
try {
|
try {
|
||||||
channel = (ChannelShell) session.openChannel("shell");
|
channel = (ChannelShell) session.openChannel("shell");
|
||||||
channel.connect();
|
channel.connect();
|
||||||
} catch (JSchException e) {
|
} catch (JSchException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
throw new IOException("打开shell通道失败", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert channel != null;
|
assert channel != null;
|
||||||
ChannelShellUtil.setDefault(channel);
|
ChannelShellUtil.setDefault(channel);
|
||||||
InputStream inputStream = channel.getInputStream();
|
InputStream inputStream = channel.getInputStream();
|
||||||
@ -176,10 +175,19 @@ public class SshCommand implements SshClient {
|
|||||||
BufferedReader br = new BufferedReader(isr, BUFF_SIZE);
|
BufferedReader br = new BufferedReader(isr, BUFF_SIZE);
|
||||||
PrintStream commander = new PrintStream(outputStream, true);
|
PrintStream commander = new PrintStream(outputStream, true);
|
||||||
|
|
||||||
for (String command : commands) {
|
// 逐条命令处理
|
||||||
commander.append(command).append(CommandConstant.ENTER);
|
for (String cmd : commands) {
|
||||||
|
String realCmd;
|
||||||
|
if (sudoPassword != null && !sudoPassword.isEmpty()) {
|
||||||
|
// 单引号转义,防止脚本内容出错
|
||||||
|
String safeCmd = cmd.replace("'", "'\\''");
|
||||||
|
realCmd = "echo " + sudoPassword + " | sudo -S bash -c '" + safeCmd + "'";
|
||||||
|
} else {
|
||||||
|
realCmd = cmd;
|
||||||
}
|
}
|
||||||
commander.append("exit" + CommandConstant.ENTER);
|
commander.append(realCmd).append(CommandConstant.ENTER);
|
||||||
|
}
|
||||||
|
commander.append("exit").append(CommandConstant.ENTER);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
char[] buff = new char[BUFF_SIZE];
|
char[] buff = new char[BUFF_SIZE];
|
||||||
|
@ -1,135 +1,175 @@
|
|||||||
package cd.casic.ci.process.util;
|
package cd.casic.ci.process.util;
|
||||||
|
|
||||||
|
|
||||||
import cn.hutool.log.Log;
|
// ... 省略 package 和 import ...
|
||||||
import com.antherd.smcrypto.sm2.Sm2;
|
import org.bouncycastle.crypto.CipherParameters;
|
||||||
import com.antherd.smcrypto.sm3.Sm3;
|
import org.bouncycastle.crypto.digests.SM3Digest;
|
||||||
import com.antherd.smcrypto.sm4.Sm4;
|
import org.bouncycastle.crypto.engines.SM2Engine;
|
||||||
import com.antherd.smcrypto.sm4.Sm4Options;
|
import org.bouncycastle.crypto.engines.SM4Engine;
|
||||||
|
import org.bouncycastle.crypto.generators.SM2KeyPairGenerator;
|
||||||
|
import org.bouncycastle.crypto.macs.HMac;
|
||||||
|
import org.bouncycastle.crypto.modes.CBCBlockCipher;
|
||||||
|
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
|
||||||
|
import org.bouncycastle.crypto.params.*;
|
||||||
|
import org.bouncycastle.crypto.signers.SM2Signer;
|
||||||
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
|
import org.bouncycastle.util.encoders.Hex;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.ECGenParameterSpec;
|
||||||
|
|
||||||
/**
|
|
||||||
* 加密工具类,本框架目前使用 https://github.com/antherd/sm-crypto 项目中一些加解密方式
|
|
||||||
* 使用小伙伴需要过等保密评相关,请在此处更改为自己的加密方法,或加密机,使用加密机同时需要替换公钥,私钥在内部无法导出,提供加密的方法
|
|
||||||
*
|
|
||||||
* @author yubaoshan
|
|
||||||
*/
|
|
||||||
public class CryptogramUtil {
|
public class CryptogramUtil {
|
||||||
|
|
||||||
private static final Log log = Log.get();
|
static {
|
||||||
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加密方法(Sm2 的专门针对前后端分离,非对称秘钥对的方式,暴露出去的公钥,对传输过程中的密码加个密)
|
* SM2 公钥加密
|
||||||
*
|
|
||||||
* @param str 待加密数据
|
|
||||||
* @return 加密后的密文
|
|
||||||
* @author yubaoshan
|
|
||||||
*/
|
*/
|
||||||
public static String doSm2Encrypt(String str) {
|
public static String doSm2Encrypt(String str) {
|
||||||
return Sm2.doEncrypt(str, Keypair.PUBLIC_KEY);
|
try {
|
||||||
|
byte[] data = str.getBytes(StandardCharsets.UTF_8);
|
||||||
|
ECPublicKeyParameters pubKey = getSm2PublicKey(Keypair.PUBLIC_KEY);
|
||||||
|
SM2Engine engine = new SM2Engine();
|
||||||
|
engine.init(true, pubKey);
|
||||||
|
byte[] enc = engine.processBlock(data, 0, data.length);
|
||||||
|
return Hex.toHexString(enc);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("SM2加密失败", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解密方法
|
* SM2 私钥解密
|
||||||
* 如果采用加密机的方法,用try catch 捕捉异常,返回原文值即可
|
|
||||||
*
|
|
||||||
* @param str 密文
|
|
||||||
* @return 解密后的明文
|
|
||||||
* @author yubaoshan
|
|
||||||
*/
|
*/
|
||||||
public static String doSm2Decrypt(String str) {
|
public static String doSm2Decrypt(String str) {
|
||||||
// 解密
|
try {
|
||||||
return Sm2.doDecrypt(str, Keypair.PRIVATE_KEY);
|
byte[] enc = Hex.decode(str);
|
||||||
|
ECPrivateKeyParameters priKey = getSm2PrivateKey(Keypair.PRIVATE_KEY);
|
||||||
|
SM2Engine engine = new SM2Engine();
|
||||||
|
engine.init(false, priKey);
|
||||||
|
byte[] dec = engine.processBlock(enc, 0, enc.length);
|
||||||
|
return new String(dec, StandardCharsets.UTF_8);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 解密失败返回原文
|
||||||
|
return str;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加密方法
|
* SM4 CBC 加密
|
||||||
*
|
|
||||||
* @param str 待加密数据
|
|
||||||
* @return 加密后的密文
|
|
||||||
* @author yubaoshan
|
|
||||||
*/
|
*/
|
||||||
public static String doEncrypt(String str) {
|
public static String doEncrypt(String str) {
|
||||||
// SM4 加密 cbc模式
|
try {
|
||||||
Sm4Options sm4Options4 = new Sm4Options();
|
byte[] key = Hex.decode(Keypair.KEY);
|
||||||
sm4Options4.setMode("cbc");
|
byte[] iv = Hex.decode(Keypair.IV);
|
||||||
sm4Options4.setIv("fedcba98765432100123456789abcdef");
|
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new SM4Engine()));
|
||||||
return Sm4.encrypt(str, Keypair.KEY, sm4Options4);
|
cipher.init(true, new ParametersWithIV(new KeyParameter(key), iv));
|
||||||
|
byte[] input = str.getBytes(StandardCharsets.UTF_8);
|
||||||
|
byte[] output = new byte[cipher.getOutputSize(input.length)];
|
||||||
|
int len = cipher.processBytes(input, 0, input.length, output, 0);
|
||||||
|
len += cipher.doFinal(output, len);
|
||||||
|
return Hex.toHexString(output, 0, len);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("SM4加密失败", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解密方法
|
* SM4 CBC 解密
|
||||||
* 如果采用加密机的方法,用try catch 捕捉异常,返回原文值即可
|
|
||||||
*
|
|
||||||
* @param str 密文
|
|
||||||
* @return 解密后的明文
|
|
||||||
* @author yubaoshan
|
|
||||||
*/
|
*/
|
||||||
public static String doDecrypt(String str) {
|
public static String doDecrypt(String str) {
|
||||||
// 解密,cbc 模式,输出 utf8 字符串
|
try {
|
||||||
Sm4Options sm4Options8 = new Sm4Options();
|
byte[] key = Hex.decode(Keypair.KEY);
|
||||||
sm4Options8.setMode("cbc");
|
byte[] iv = Hex.decode(Keypair.IV);
|
||||||
sm4Options8.setIv("fedcba98765432100123456789abcdef");
|
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new SM4Engine()));
|
||||||
String docString = Sm4.decrypt(str, Keypair.KEY, sm4Options8);
|
cipher.init(false, new ParametersWithIV(new KeyParameter(key), iv));
|
||||||
if (docString.equals("")) {
|
byte[] input = Hex.decode(str);
|
||||||
log.warn(">>> 字段解密失败,返回原文值:{}", str);
|
byte[] output = new byte[cipher.getOutputSize(input.length)];
|
||||||
|
int len = cipher.processBytes(input, 0, input.length, output, 0);
|
||||||
|
len += cipher.doFinal(output, len);
|
||||||
|
return new String(output, 0, len, StandardCharsets.UTF_8);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 解密失败返回原文
|
||||||
return str;
|
return str;
|
||||||
} else {
|
|
||||||
return docString;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 纯签名
|
* SM2 签名
|
||||||
*
|
|
||||||
* @param str 待签名数据
|
|
||||||
* @return 签名结果
|
|
||||||
* @author yubaoshan
|
|
||||||
*/
|
*/
|
||||||
public static String doSignature(String str) {
|
public static String doSignature(String str) {
|
||||||
return Sm2.doSignature(str, Keypair.PRIVATE_KEY);
|
try {
|
||||||
|
ECPrivateKeyParameters priKey = getSm2PrivateKey(Keypair.PRIVATE_KEY);
|
||||||
|
SM2Signer signer = new SM2Signer();
|
||||||
|
signer.init(true, priKey);
|
||||||
|
byte[] msg = str.getBytes(StandardCharsets.UTF_8);
|
||||||
|
signer.update(msg, 0, msg.length);
|
||||||
|
byte[] sig = signer.generateSignature();
|
||||||
|
return Hex.toHexString(sig);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("SM2签名失败", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证签名结果
|
* SM2 验签
|
||||||
*
|
|
||||||
* @param originalStr 签名原文数据
|
|
||||||
* @param str 签名结果
|
|
||||||
* @return 是否通过
|
|
||||||
* @author yubaoshan
|
|
||||||
*/
|
*/
|
||||||
public static boolean doVerifySignature(String originalStr, String str) {
|
public static boolean doVerifySignature(String originalStr, String str) {
|
||||||
return Sm2.doVerifySignature(originalStr, str, Keypair.PUBLIC_KEY);
|
try {
|
||||||
|
ECPublicKeyParameters pubKey = getSm2PublicKey(Keypair.PUBLIC_KEY);
|
||||||
|
SM2Signer signer = new SM2Signer();
|
||||||
|
signer.init(false, pubKey);
|
||||||
|
byte[] msg = originalStr.getBytes(StandardCharsets.UTF_8);
|
||||||
|
signer.update(msg, 0, msg.length);
|
||||||
|
byte[] sig = Hex.decode(str);
|
||||||
|
return signer.verifySignature(sig);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过杂凑算法取得hash值,用于做数据完整性保护
|
* SM3 哈希
|
||||||
*
|
|
||||||
* @param str 字符串
|
|
||||||
* @return hash 值
|
|
||||||
* @author yubaoshan
|
|
||||||
*/
|
*/
|
||||||
public static String doHashValue(String str) {
|
public static String doHashValue(String str) {
|
||||||
return Sm3.sm3(str);
|
try {
|
||||||
|
SM3Digest digest = new SM3Digest();
|
||||||
|
byte[] msg = str.getBytes(StandardCharsets.UTF_8);
|
||||||
|
digest.update(msg, 0, msg.length);
|
||||||
|
byte[] hash = new byte[digest.getDigestSize()];
|
||||||
|
digest.doFinal(hash, 0);
|
||||||
|
return Hex.toHexString(hash);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("SM3哈希失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====== 工具方法 ======
|
||||||
|
|
||||||
|
// 获取SM2公钥参数
|
||||||
|
private static ECPublicKeyParameters getSm2PublicKey(String hex) {
|
||||||
|
org.bouncycastle.jce.spec.ECParameterSpec ecSpec = org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec("sm2p256v1");
|
||||||
|
org.bouncycastle.math.ec.ECPoint q = ecSpec.getCurve().decodePoint(Hex.decode(hex));
|
||||||
|
return new ECPublicKeyParameters(q, new ECDomainParameters(ecSpec.getCurve(), ecSpec.getG(), ecSpec.getN()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取SM2私钥参数
|
||||||
|
private static ECPrivateKeyParameters getSm2PrivateKey(String hex) {
|
||||||
|
org.bouncycastle.jce.spec.ECParameterSpec ecSpec = org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec("sm2p256v1");
|
||||||
|
return new ECPrivateKeyParameters(new java.math.BigInteger(hex, 16), new ECDomainParameters(ecSpec.getCurve(), ecSpec.getG(), ecSpec.getN()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Keypair {
|
private static class Keypair {
|
||||||
|
// 公钥(未压缩点,hex字符串,前缀04)
|
||||||
/**
|
public static final String PUBLIC_KEY = "04298364ec840088475eae92a591e01284d1abefcda348b47eb324bb521bb03b0b2a5bc393f6b71dabb8f15c99a0050818b56b23f31743b93df9cf8948f15ddb54";
|
||||||
* 公钥
|
// 私钥(hex字符串)
|
||||||
*/
|
public static final String PRIVATE_KEY = "3037723d47292171677ec8bd7dc9af696c7472bc5f251b2cec07e65fdef22e25";
|
||||||
public static String PUBLIC_KEY = "04298364ec840088475eae92a591e01284d1abefcda348b47eb324bb521bb03b0b2a5bc393f6b71dabb8f15c99a0050818b56b23f31743b93df9cf8948f15ddb54";
|
// SM4密钥(16字节,128位,hex字符串)
|
||||||
|
public static final String KEY = "0123456789abcdeffedcba9876543210";
|
||||||
/**
|
// SM4 IV(16字节,hex字符串)
|
||||||
* 私钥
|
public static final String IV = "fedcba98765432100123456789abcdef";
|
||||||
*/
|
|
||||||
public static String PRIVATE_KEY = "3037723d47292171677ec8bd7dc9af696c7472bc5f251b2cec07e65fdef22e25";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SM4的对称秘钥(生产环境需要改成自己使用的)
|
|
||||||
* 16 进制字符串,要求为 128 比特
|
|
||||||
*/
|
|
||||||
public static String KEY = "0123456789abcdeffedcba9876543210";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user