package private_ca import ( "ALLinSSL/backend/public" "encoding/json" "fmt" "time" ) func CreateRootCA(name, commonName, organization, organizationalUnit, country, province, locality, keyType string, keyBits, validDays int64) error { var err error var data *CAConfig if keyType == "sm2" { // 国密SM2根证书 - 生成签名和加密双证书, 使用不同私钥 data, err = GenerateRootCASM2(name, commonName, organization, organizationalUnit, country, province, locality, int(validDays)) } else { // 标准根证书 - 生成单一证书 data, err = GenerateRootCAStandard(name, commonName, organization, organizationalUnit, country, province, locality, KeyType(keyType), int(keyBits), int(validDays)) } if err != nil { return err } // 保存到数据库 s, err := GetSqlite() if err != nil { return err } defer s.Close() _, err = s.Insert(public.StructToMap(data, true)) if err != nil { return err } return nil } func CreateIntermediateCA(name, commonName, organization, organizationalUnit, country, province, locality string, rootId, keyBits, validDays int64) error { s, err := GetSqlite() if err != nil { return err } defer s.Close() issuers, err := s.Where("id=?", []interface{}{rootId}).Select() if err != nil { return err } if len(issuers) == 0 { return fmt.Errorf("issuer with id %d not found", rootId) } issuer := issuers[0] keyType := issuer["algorithm"].(string) cert := issuer["cert"].(string) key := issuer["key"].(string) var data *CAConfig if keyType == "sm2" { // 国密SM2中级证书 - 生成签名和加密双证书, 使用不同私钥 enCert := issuer["en_cert"].(string) enKey := issuer["en_key"].(string) data, err = GenerateIntermediateCASM2(name, commonName, organization, organizationalUnit, country, province, locality, cert, key, enCert, enKey, int(validDays)) } else { // 标准中级证书 - 生成单一证书 data, err = GenerateIntermediateCAStandard(name, commonName, organization, organizationalUnit, country, province, locality, cert, key, keyType, int(keyBits), int(validDays)) } if err != nil { return err } // 保存到数据库 insertData := public.StructToMap(data, true) insertData["root_id"] = rootId _, err = s.Insert(insertData) if err != nil { return err } return nil } func DeleteCA(id int64) error { s, err := GetSqlite() if err != nil { return err } defer s.Close() // 检查是否有子证书 children, err := s.Where("root_id=?", []interface{}{id}).Select() if err != nil { return err } if len(children) > 0 { return fmt.Errorf("cannot delete CA with id %d: it has child CAs", id) } _, err = s.Where("id=?", []interface{}{id}).Delete() if err != nil { return err } return nil } func ListCAs(search, level string, p, limit int64) ([]map[string]interface{}, int, error) { s, err := GetSqlite() if err != nil { return nil, 0, err } defer s.Close() var data []map[string]any var count int64 var limits []int64 if p >= 0 && limit >= 0 { limits = []int64{0, limit} if p > 1 { limits[0] = (p - 1) * limit limits[1] = limit } } whereStr := "1=1" var params []interface{} if search != "" { whereStr += " and (name like ? or cn like ?)" params = append(params, "%"+search+"%", "%"+search+"%") } if level == "root" { whereStr += " and root_id is null" } if level == "intermediate" { whereStr += " and root_id is not null" } data, err = s.Where(whereStr, params).Limit(limits).Order("create_time", "desc").Select() count, err = s.Where(whereStr, params).Limit(limits).Count() if err != nil { return data, int(count), err } return data, int(count), nil } func CreateLeafCert(caId, usage, keyBits, validDays int64, cn, san string) (*LeafCertConfig, error) { if caId <= 0 { return nil, fmt.Errorf("CA ID不能为空") } if san == "" { return nil, fmt.Errorf("备用名称不能为空") } var sans SAN err := json.Unmarshal([]byte(san), &sans) if err != nil { return nil, fmt.Errorf("备用名称格式错误: %v", err) } if cn == "" { if len(sans.DNSNames) > 0 { cn = sans.DNSNames[0] } else if len(sans.IPAddresses) > 0 { cn = string(sans.IPAddresses[0]) } else if len(sans.EmailAddresses) > 0 { cn = sans.EmailAddresses[0] } else { return nil, fmt.Errorf("CN和SAN不能为空") } } s, err := GetSqlite() if err != nil { return nil, err } defer s.Close() issuers, err := s.Where("id=?", []interface{}{caId}).Select() if err != nil { return nil, err } if len(issuers) == 0 { return nil, fmt.Errorf("issuer with id %d not found", caId) } issuer := issuers[0] if issuer["root_id"] == "" || issuer["root_id"] == nil { return nil, fmt.Errorf("不允许使用根证书直接签发叶子证书,请先创建中间证书") } keyType := issuer["algorithm"].(string) cert := issuer["cert"].(string) key := issuer["key"].(string) var issuerObj *Certificate if keyType == "sm2" { enCert := issuer["en_cert"].(string) enKey := issuer["en_key"].(string) issuerObj, err = NewCertificateFromPEMSM2([]byte(cert), []byte(key), []byte(enCert), []byte(enKey)) } else { issuerObj, err = NewCertificateFromPEMStandard([]byte(cert), []byte(key), KeyType(keyType)) } leafObj, err := GenerateLeafCertificate(cn, sans, issuerObj, KeyType(keyType), int(usage), int(keyBits), int(validDays)) if err != nil { return nil, err } s.TableName = "leaf" // 保存到数据库 leafObj.SAN = san leafObj.CaId = caId insertData := public.StructToMap(leafObj, true) _, err = s.Insert(insertData) if err != nil { return nil, err } return leafObj, nil } func ListLeafCerts(caId int64, search string, p, limit int64) ([]map[string]interface{}, int, error) { s, err := GetSqlite() if err != nil { return nil, 0, err } defer s.Close() s.TableName = "leaf" var data []map[string]any var count int64 var limits []int64 sql := ` select leaf.*, ca.name as ca_name, ca.cn as ca_cn from leaf left join ca on leaf.ca_id = ca.id where 1=1 ` // 拼接查询条件 var params []interface{} if caId > 0 { sql += " and leaf.ca_id = ?" params = append(params, caId) } if search != "" { sql += " and (leaf.cn like ? or leaf.san like ?)" params = append(params, "%"+search+"%", "%"+search+"%") } sql += " order by leaf.create_time desc" sqlCount := "select count(id) as count from (" + sql + ")" if p > 0 && limit > 0 { limits = []int64{0, limit} if p > 1 { limits[0] = (p - 1) * limit limits[1] = limit } sql += fmt.Sprintf(" limit %d offset %d", limits[1], limits[0]) } data, err = s.Query(sql, params...) if err != nil { return data, 0, err } countResult, err := s.Query(sqlCount, params...) if err != nil { return data, 0, err } if len(countResult) > 0 { count = countResult[0]["count"].(int64) } return data, int(count), nil } func DeleteLeafCert(id int64) error { s, err := GetSqlite() if err != nil { return err } defer s.Close() s.TableName = "leaf" _, err = s.Where("id=?", []interface{}{id}).Delete() if err != nil { return err } return nil } func GetCert(id int64, certType string) (map[string]any, error) { s, err := GetSqlite() if err != nil { return nil, err } defer s.Close() s.TableName = certType leafs, err := s.Where("id=?", []interface{}{id}).Select() if err != nil { return nil, err } if len(leafs) == 0 { return nil, fmt.Errorf("leaf cert with id %d not found", id) } return leafs[0], nil } func WorkflowCreateLeafCert(params map[string]any, logger *public.Logger) (map[string]any, error) { caId, ok := params["ca_id"].(float64) if !ok || caId <= 0 { return nil, fmt.Errorf("ca_id参数错误") } keyBits, ok := params["key_length"].(float64) if !ok { return nil, fmt.Errorf("key_length参数错误") } validDays, ok := params["valid_days"].(float64) if !ok { return nil, fmt.Errorf("valid_days参数错误") } endDay, ok := params["end_day"].(float64) if !ok { endDay = 0 } cn, ok := params["cn"].(string) if !ok { cn = "" } san, ok := params["san"].(string) if !ok || san == "" { return nil, fmt.Errorf("san参数错误") } // 先获取ca信息,确认是中间证书且不能是国密 s, err := GetSqlite() if err != nil { return nil, err } defer s.Close() issuers, err := s.Where("id=?", []interface{}{caId}).Select() if err != nil { return nil, err } if len(issuers) == 0 { return nil, fmt.Errorf("issuer with id %d not found", caId) } issuer := issuers[0] if issuer["root_id"] == "" || issuer["root_id"] == nil { return nil, fmt.Errorf("不允许使用根证书直接签发叶子证书,请先创建中间证书") } keyType := issuer["algorithm"].(string) if keyType == "sm2" { return nil, fmt.Errorf("暂不兼容国密证书,请使用标准证书") } // 判断中间证书不能为已过期,过期时间不能超过中间证书 caNotAfter, err := time.Parse("2006-01-02 15:04:05", issuer["not_after"].(string)) if err != nil { return nil, fmt.Errorf("解析中间证书过期时间失败: %v", err) } maxValidDays := caNotAfter.Sub(time.Now()).Hours() / 24 if maxValidDays <= 0 { return nil, fmt.Errorf("中间证书已过期,不能签发叶子证书") } if validDays > maxValidDays { return nil, fmt.Errorf("叶子证书的有效期不能超过中间证书的有效期,中间证书将在 %s 过期,距离今天还有 %d 天", caNotAfter.Format("2006-01-02"), int(maxValidDays)) } // 解析san,判断数据库中是否已存在相同的cn和san var sans SAN err = json.Unmarshal([]byte(san), &sans) if err != nil { return nil, fmt.Errorf("备用名称格式错误: %v", err) } if cn == "" { if len(sans.DNSNames) > 0 { cn = sans.DNSNames[0] } else { cn = string(sans.IPAddresses[0]) } } s.TableName = "leaf" // 获取所有未过期的证书,判断是否有相同的cn和san leafs, err := s.Where("ca_id=? and not_after>? and usage=1", []interface{}{caId, time.Now().Format("2006-01-02 15:04:05")}).Select() if err != nil { return nil, err } var certificate map[string]any for _, v := range leafs { // 判断剩余天数是否满足要求 if endDay > 0 { notAfter, err := time.Parse("2006-01-02 15:04:05", v["not_after"].(string)) if err != nil { continue } remainDays := notAfter.Sub(time.Now()).Hours() / 24 if remainDays < endDay { continue } } // 判断cn和san是否相同 if v["cn"] == cn { var existingSAN SAN err = json.Unmarshal([]byte(v["san"].(string)), &existingSAN) if err != nil { continue } if public.ContainsAllIgnoreBRepeats(existingSAN.DNSNames, sans.DNSNames) { var existingIPs, newIPs []string for _, ip := range existingSAN.IPAddresses { existingIPs = append(existingIPs, ip.String()) } for _, ip := range sans.IPAddresses { newIPs = append(newIPs, ip.String()) } if public.ContainsAllIgnoreBRepeats(existingIPs, newIPs) { // 找到相同的证书,标记为跳过 logger.Debug("找到相同的证书,跳过创建", "id", v["id"]) certificate = map[string]any{ "cert": v["cert"], "key": v["key"], "skip": true, } break } } } } if certificate == nil { leaf, err := CreateLeafCert(int64(caId), 1, int64(keyBits), int64(validDays), cn, san) if err != nil { return nil, err } certificate = map[string]any{ "cert": leaf.Cert, "key": leaf.Key, } } return certificate, nil }