FIELD NOTE
证书自动导入Windows-golang实现
命令
查看当前用户的受信任根证书:
certutil -user -store Root
为了兼容性,还需要查看本地计算机的受信任根证书:
certutil -store Root
导入证书到当前用户的受信任根证书:
certutil -user -addstore Root ca.crt
其中 ca.crt为需要导入的根证书。
代码
实际代码中还要考虑cmd输出的内容可能不是UFT-8编码,而是GB2312编码。此时为了日志可读性,需要进行编码转换。
// CertImport 自动导入证书
// 先判断证书是否已经存在,如果存在则不导入
// 否则导入证书
func CertImport() {
logger.Info("开始导入证书")
cmd := exec.Command("certutil", "-user", "-store", "Root")
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
bytesOut := bytes.NewBuffer([]byte{})
cmd.Stdout = bytesOut
err := cmd.Run()
if err != nil {
logger.Errorf("certutil -user -store Root执行报错:%v", errors.WithStack(err))
return
}
exist := false
var outData []byte
outData, err = gb2312ToUTF8(bytesOut.Bytes())
if err != nil {
logger.Errorf("gb2312转utf8报错:%v", errors.WithStack(err))
return
}
if bytes.Contains(outData, []byte("macdfree@163.com")) {
exist = true
logger.Infof("证书已经存在或命令执行报错:%s", string(outData))
}
if !exist {
cmd = exec.Command("certutil", "-store", "Root")
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
bytesOut = bytes.NewBuffer([]byte{})
cmd.Stdout = bytesOut
err = cmd.Run()
if err != nil {
logger.Errorf("certutil -store Root执行报错:%v", errors.WithStack(err))
return
}
outData, err = gb2312ToUTF8(bytesOut.Bytes())
if err != nil {
logger.Errorf("gb2312转utf8报错:%v", errors.WithStack(err))
return
}
if bytes.Contains(outData, []byte("macdfree@163.com")) {
exist = true
logger.Infof("证书已经存在或命令执行报错:%s", string(outData))
}
}
if !exist {
cmd := exec.Command("certutil", "-user", "-addstore", "Root", "ca.crt")
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
bytesOut = bytes.NewBuffer([]byte{})
cmd.Stdout = bytesOut
err = cmd.Run()
if err != nil {
logger.Errorf("certutil -user -addstore Root ca.crt执行报错:%v", errors.WithStack(err))
return
}
outData, err = gb2312ToUTF8(bytesOut.Bytes())
if err != nil {
logger.Errorf("gb2312转utf8报错:%v", errors.WithStack(err))
return
}
logger.Infof("自动导入证书执行结果:%s", string(outData))
}
}
func isGB2312(data []byte) bool {
i := 0
count := 0
for i < len(data) {
// 如果第一个字节的范围在0xA1到0xF7
if data[i] >= 0xA1 && data[i] <= 0xF7 {
// 检查第二个字节是否在0xA1到0xFE范围内
if i+1 < len(data) && data[i+1] >= 0xA1 && data[i+1] <= 0xFE {
count++
i += 2
} else {
i++
}
} else {
i++
}
}
logger.Infof("检测GB2312编码,匹配数为:%d", count)
if count > 2 {
return true
} else {
return false
}
}
func gb2312ToUTF8(gb2312Bytes []byte) ([]byte, error) {
if !isGB2312(gb2312Bytes) {
logger.Infof("不是GB2312编码,直接返回:%s", string(gb2312Bytes))
return gb2312Bytes, nil
}
transformer := simplifiedchinese.GB18030.NewDecoder()
// 使用transformer将GB2312解码为UTF-8
utf8Bytes, _, err := transform.Bytes(transformer, gb2312Bytes)
if err != nil {
return nil, err
}
return utf8Bytes, nil
}
参考
https://learn.microsoft.com/zh-cn/windows-server/administration/windows-commands/certutil
评论