这属于测试性质的证书使用,不会被第三方认可。正式环境还是需要获取CA签名的证书。构建自己的证书代码如下:
// "CN" 通用名
// "O",// 组织
// "C", // 国家代码
// "ST", // 州或省份
X500Name subject = new X500Name("CN=公司数字签名, O=上海XX股份有限公司, C=CN, ST= 上海");
Calendar start = Calendar.getInstance();
Calendar expiry = Calendar.getInstance();
expiry.add(Calendar.YEAR, 1);
//证书的扩展信息
ExtensionsGenerator extGenerator = new ExtensionsGenerator();
extGenerator.addExtension(X509Extension.basicConstraints, false, new BasicConstraints(false));
KeyUsage keyUsage = new KeyUsage(KeyUsage.digitalSignature | KeyUsage.nonRepudiation);
extGenerator.addExtension(X509Extension.keyUsage, false, keyUsage);
//使用easy构建国密证书 GMX509Builder
GMX509Builder gmx509Builder= GMX509Builder.getInstance(new BigInteger("2315416525683890325"),subject,start,expiry,extGenerator);
工业和信息化部许可的55家CA机构名单:
序号 | CA机构名称 | 地区 | 序号 | CA机构名称 | 地区 |
---|---|---|---|---|---|
1 | 中金金融认证中心有限公司 | 北京 | 31 | 上海市数字证书认证中心有限公司 | 上海 |
2 | 北京天威诚信电子商务服务有限公司 | 北京 | 32 | 亚数信息科技(上海)有限公司 | 上海 |
3 | 北京数字认证股份有限公司 | 北京 | 33 | 山东省数字证书认证管理有限公司 | 山东 |
4 | 颐信科技有限公司 | 北京 | 34 | 山东豸信认证服务有限公司(原山东云海) | 山东 |
5 | 北京国富安电子商务安全认证有限公司 | 北京 | 35 | 华测电子认证有限责任公司 | 河南 |
6 | 联通智慧安全科技有限公司 | 北京 | 36 | 河南省信息化发展有限公司 | 河南 |
7 | 北京中认环宇信息安全技术有限公司 | 北京 | 37 | 浙江省数字安全证书管理有限公司 | 浙江 |
8 | 中铁信弘远(北京)软件科技有限责任公司 | 北京 | 38 | 云南省数字证书认证中心有限公司 | 云南 |
9 | 北京世纪速码信息科技有限公司 | 北京 | 39 | 新疆数字证书认证中心(有限公司) | 新疆 |
10 | 农信银资金清算中心有限责任公司 | 北京 | 40 | 四川省数字证书认证管理中心有限公司 | 四川 |
11 | 中国电力科学研究院有限公司 | 北京 | 41 | 陕西省数字证书认证中心股份有限公司 | 陕西 |
12 | 泰尔认证中心有限公司 | 北京 | 42 | 山西省数字证书认证中心(有限公司) | 山西 |
13 | 国汽(北京)智能网联汽车研究院有限公司 | 北京 | 43 | 西部安全认证中心有限责任公司 | 宁夏 |
14 | 广东省电子商务认证有限公司 | 广东 | 44 | 内蒙古网信电子认证有限责任公司 | 内蒙 |
15 | 数安时代科技股份有限公司 | 广东 | 45 | 辽宁数字证书认证管理有限公司 | 辽宁 |
16 | 深圳市电子商务安全证书管理有限公司 | 广东 | 46 | 江西省数字证书有限公司 | 江西 |
17 | 卓望数码技术(深圳)有限公司 | 广东 | 47 | 吉林省安信电子认证服务有限公司 | 吉林 |
18 | 沃通电子认证服务有限公司 | 广东 | 48 | 湖北省数字证书认证管理中心有限公司 | 湖北 |
19 | 江苏省国信数字科技有限公司 | 江苏 | 49 | 黑龙江省数字证书认证有限公司 | 黑龙江 |
20 | 江苏智慧数字认证有限公司 | 江苏 | 50 | 河北省电子认证有限公司 | 河北 |
21 | 江苏国密数字认证有限公司 | 江苏 | 51 | 海南省信安电子认证有限公司 | 海南 |
22 | 南京数字认证有限公司 | 江苏 | 52 | 贵州省电子证书有限公司 | 贵州 |
23 | 东方中讯数字证书认证有限公司 | 重庆 | 53 | 广西壮族自治区数字证书认证中心有限公司 | 广西 |
24 | 重庆程远未来电子商务服务有限公司 | 重庆 | 54 | 福建省数字安全证书管理有限公司 | 福建 |
25 | 大陆云盾电子认证服务有限公司 | 重庆 | 55 | 安徽省电子认证管理中心有限责任公司 | 安徽 |
26 | 湖南省数字认证服务中心有限公司 | 湖南 | |||
27 | 东方新诚信数字认证中心有限公司 | 湖南 | |||
28 | 苏博云科数字认证有限公司 | 湖南 | |||
29 | 天津市滨海数字认证有限公司 | 天津 | |||
30 | 天津市中环认证服务有限公司 | 天津 |
关于数字证书的基础知识大家可以参考如下连接:
信息安全技术公钥基础设施 数字证书格式 GB/T 20518-2018
X509 V3版本
X509 V3版本 中英对照
本小节主要说明了如何构建一个自己签发的数字证书对文件进行数字签名,主要包括一下步骤:
主要代码如下:
String filePath2 = "XML/image/image.ofd"; // 需要签名的文件
String filePath1 = "XML/signs/image-signs.ofd"; // 签名后的文件
//第一步,构建自己的数字证书
GMX509Builder gmx509Builder=getCertificate(); //构造自定义数字证书,私钥及其秘钥
X509Certificate certificate= gmx509Builder.getCertificate();
//第二步,声明签名类
OFDSingnatures fileSingnatures=new OFDSingnatures(new File(filePath2),certificate);
BCECPrivateKey bcecPrivateKey=(BCECPrivateKey) gmx509Builder.getPrivateKey() ;
// 第三步,利用私钥对文件进行签名
fileSingnatures.siqn(bcecPrivateKey);
// 第四步,保存文件
try {
OutputStream os = null;
os = new FileOutputStream(filePath1);
fileSingnatures.saveOFD(os);
if(os!=null)
{
os.flush();
os.close();
}
} catch (Exception e) {
e.printStackTrace();
}
与自定义数字证书类似,主要是数字证书的获取方式不同,主要包括一下步骤:
主要代码如下:
String filePath2 = "XML/image/image.ofd"; // ASN.1文件路径
String filePath1 = "XML/signs/image-signs-2.ofd"; // ASN.1文件路径
//第一步:获取颁发的证书和私钥
X509Certificate x509Certificate= GMX509Builder.getInstance("key/ofd.cert.pem");
PrivateKey privateKey= getPrivateKey();
//第二步,声明签名类
OFDSingnatures fileSingnatures=new OFDSingnatures(new File(filePath2),certificate);
BCECPrivateKey bcecPrivateKey=(BCECPrivateKey) privateKey ;
// 第三步,利用私钥对文件进行签名
fileSingnatures.siqn(bcecPrivateKey);
// 第四步,保存文件
try {
OutputStream os = null;
os = new FileOutputStream(filePath1);
fileSingnatures.saveOFD(os);
if(os!=null)
{
os.flush();
os.close();
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("aaaaaa");
}catch (Exception ex) {
Assert.fail(ex.getMessage());
}
}
读取私钥的方法如下:
public PrivateKey getPrivateKey() throws NoSuchProviderException, InvalidKeySpecException {
String pemFilePath = "key/ofd.key.pem"; // 私钥文件
PrivateKey privateKey=null;
try (FileReader fileReader = new FileReader(pemFilePath)) {
PEMParser pemParser = new PEMParser(fileReader);
org.bouncycastle.openssl.PEMKeyPair pemPair = (org.bouncycastle.openssl.PEMKeyPair) pemParser.readObject();
privateKey = new JcaPEMKeyConverter().getPrivateKey(pemPair.getPrivateKeyInfo());
} catch (IOException e) {
e.printStackTrace();
}
return privateKey;
}
验签是很简单的过程,只要把需要验签的文件传递给OFDVerifySignature类,调用verifySignature方法即可,只有该方法返回是true的情况才属于验签通过。
目前该版本程序验签只负责核对签名文件是否被修改进行验证,不会对证书的有效性,证书链,是否被吊销,是否过期等进行检核。
//需要验签的文件
String filePath = "XML/signs/image-signs.ofd";
OFDVerifySignature ofdVerifySignature =new OFDVerifySignature(new File(filePath));
//验签的结果
boolean verifySignature = ofdVerifySignature.verifySignature();
不过你可以实现ISignsCheck接口来定义你自己的检核程序。参数ContentInfo,包含了签名的值详细内容见 加密签名消息规范 GB/T 35275
public boolean signsCheck(ContentInfo contentInfo) {
System.out.println("your check ....");
return true;
}