安全证书 - 了解代码签名中的CA角色

时间:2015-02-21 22:38:22

标签: java cryptography certificate public-key-encryption public-key

我是公共密码学的新手。我清楚地了解它,但我对过去8周无法解决的一些问题感到困惑。所以我会尽可能清楚地解释,以表达我的困惑。

我试图理解CA公共证书和代码签名的作用,从而手动模拟这种情况。

密钥库
acmesoft.jks(充当CA)
cindy.jks(acmesoft员工)
me.jks(acmesoft员工)

初步设置
Acmesoft生成密钥对并将其公钥分发给员工(CA证书)
cindy将CA证书导入cindy.jks
我将CA证书导入me.jks

目标
我想要jar一些文件,生成一个证书(ME证书),让acmesoft(CA)签署证书并签署jar文件发送给cindy

这是我的困惑 为了实现上述目标哪个过程是正确的?

按时间顺序排列的进程1
我生成密钥对(ME证书)
我罐子里的文件(ME罐子)
ME证书已发送到CA(CA将使用其私钥进行签名.ME signed_cert将具有带有CA私钥签名的ME公钥)
我把这个ME签名给了cindy cindy导入ME signed_cert可信证书,因为cindy之前已经导入了CA证书 我用ME私钥(不是ME signed_cert)签署了ME jar 我把ME jar文件给cindy cindy在ME jar上做了一个jarsigner验证

流程1问题
Cindy密钥库将具有ME signed_certs,其由ME公钥和CA签名组成。 cindy.jks上的ME jar上的jarsigner验证显示没有找到密钥。

我预计它会显示密钥,因为cindy.jks中的ME signed_cert具有带有CA私有签名的ME公钥,而ME jar文件是使用ME私钥签名的。

流程2
正如过程1但是:
我将返回的ME signed_certs从acmesoft(由ME公钥和CA签名组成)导入到ME jks中 我使用jarsigner签署ME jar文件

流程2问题
签字后,小丑们投诉如下:

jarsigner:找不到证书链:primary_root。 primary_root必须引用包含私钥和相应公钥证书链的有效KeyStore密钥条目。

当然我得到了上述错误。 ME.jks没有CA的私钥。我不应该有CA私钥。

所以我不确定过程2的工作原理。这是正确的还是我的理解是错误的。

以下是实际的密钥库:

acmesoft

Alias name: acmeroot
Creation date: 2-Feb-2015
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=acmesoft, OU=information resources department, O=certificate authority, L=toronto, ST=ontario, C=ca
Issuer: CN=acmesoft, OU=information resources department, O=certificate authority, L=toronto, ST=ontario, C=ca
Serial number: 381e5a1f
Valid from: Mon Feb 02 00:01:14 EST 2015 until: Sun May 03 01:01:14 EDT 2015
Certificate fingerprints:
 MD5:  94:A1:76:2F:D5:05:8D:3C:2C:0F:B2:07:EC:9A:1E:12
 SHA1: AD:0A:28:AD:D9:42:C8:B3:C7:7D:CB:36:6F:EF:2C:99:50:00:30:3C
 SHA256: 31:14:A0:F8:51:72:37:7C:F5:25:6C:3A:F3:10:74:D8:F8:2B:B8:BC:FE:C7:F3:56:89:00:C4:6B:36:48:B2:A4
 Signature algorithm name: SHA1withDSA
 Version: 3

ME密钥库

Alias name: ME
Creation date: 23-Jan-2015
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=kim yap, OU=rbss, O=cibc, L=toronto, ST=ontario, C=ca
Issuer: CN=kim yap, OU=rbss, O=cibc, L=toronto, ST=ontario, C=ca
Serial number: 4ecdc79c
Valid from: Fri Jan 23 11:10:12 EST 2015 until: Thu Apr 23 12:10:12 EDT 2015
Certificate fingerprints:
 MD5:  1A:FC:CF:40:4B:F7:1E:57:ED:28:1E:9B:5A:86:82:3E
 SHA1: 74:02:90:B5:DE:76:D4:04:21:23:2B:B8:6F:7C:B5:D4:41:5B:91:FB
 SHA256: B9:F6:A7:75:89:9F:0B:1F:29:DA:29:71:C1:18:1E:2D:BB:2F:35:41:4F:BA:D7:7C:50:CD:1A:CC:54:B7:12:37
 Signature algorithm name: SHA1withDSA
 Version: 3

Public Key: 02 81 80 79 14 21 28 57 EF 30 0D 98 0D 1A 8B EB 35 C3 76 06 0C FC DC D1 40 A6 0B 30 A4 F0 6E 24 AC 92 2D 44 F9 8F BB F9 51 6D 7F 99 F2 18 A4 55 2F D4 4A 1D 4F CC 9B 3D 5F 00 F6 95 58 77 E3 7E AD 2D 87 79 B7 9F BD 35 1D DC AF 7E 24 EC C7 09 20 C4 3D CA E6 5F 59 49 A9 00 DC 4B 06 CF 37 30 65 4E AC CB 80 50 F4 F4 21 8E DD 81 99 14 AA 9E 3A 07 C3 1B 2E 76 61 F9 B8 51 2A E0 A6 BA 55 0E DB 90 19

cindy keystores

Alias name: acmeroot
Creation date: 2-Feb-2015
Entry type: trustedCertEntry

Owner: CN=acmesoft, OU=information resources department, O=certificate authority, L=toronto, ST=ontario, C=ca
Issuer: CN=acmesoft, OU=information resources department, O=certificate authority, L=toronto, ST=ontario, C=ca
Serial number: 381e5a1f
Valid from: Mon Feb 02 00:01:14 EST 2015 until: Sun May 03 01:01:14 EDT 2015
Certificate fingerprints:
 MD5:  94:A1:76:2F:D5:05:8D:3C:2C:0F:B2:07:EC:9A:1E:12
 SHA1: AD:0A:28:AD:D9:42:C8:B3:C7:7D:CB:36:6F:EF:2C:99:50:00:30:3C
 SHA256: 31:14:A0:F8:51:72:37:7C:F5:25:6C:3A:F3:10:74:D8:F8:2B:B8:BC:FE:C7:F3:56:89:00:C4:6B:36:48:B2:A4
 Signature algorithm name: SHA1withDSA
 Version: 3

*******************************************
*******************************************

Alias name: ME_signedby_acmesoft
Creation date: 11-Feb-2015
Entry type: trustedCertEntry

Owner: CN=kim yap, OU=rbss, O=cibc, L=toronto, ST=ontario, C=ca
Issuer: CN=acmesoft, OU=information resources department, O=certificate authority, L=toronto, ST=ontario, C=ca
Serial number: 4ecdc79c
Valid from: Fri Jan 23 11:10:12 EST 2015 until: Thu Apr 23 12:10:12 EDT 2015
Certificate fingerprints:
 MD5:  AF:27:8B:63:86:A7:3F:FE:D9:03:64:3E:AB:7E:CE:DF
 SHA1: 2E:8A:78:ED:14:12:00:78:67:91:EE:8D:79:45:56:34:FC:17:02:FE
 SHA256: 28:60:A4:20:F1:7E:D3:3B:11:7E:D1:A1:04:F3:3C:70:43:92:91:16:CD:D6:96:A6:CC:71:94:10:1B:26:9D:09
 Signature algorithm name: SHA1withDSA
 Version: 3

Public Key: 02 81 80 79 14 21 28 57 EF 30 0D 98 0D 1A 8B EB 35 C3 76 06 0C FC DC D1 40 A6 0B 30 A4 F0 6E 24 AC 92 2D 44 F9 8F BB F9 51 6D 7F 99 F2 18 A4 55 2F D4 4A 1D 4F CC 9B 3D 5F 00 F6 95 58 77 E3 7E AD 2D 87 79 B7 9F BD 35 1D DC AF 7E 24 EC C7 09 20 C4 3D CA E6 5F 59 49 A9 00 DC 4B 06 CF 37 30 65 4E AC CB 80 50 F4 F4 21 8E DD 81 99 14 AA 9E 3A 07 C3 1B 2E 76 61 F9 B8 51 2A E0 A6 BA 55 0E DB 90 19

除了Cay Horstmann的证书签名(模拟CA)上的CoreJava 2之外的原始版本。

在"验证签名"在第814页,您看到Alice如何使用自签名证书来分发 Bob的公钥。但是,Bob需要通过验证指纹来确保证书有效 爱丽丝。 假设爱丽丝想给她的同事辛迪发一条签名的信息,但辛迪并不想打扰 验证大量签名指纹。现在假设有一个Cindy信任的实体来验证签名。 在这个例子中,Cindy信任ACME Software的信息资源部门。 该部门运营证书颁发机构(CA)。 ACME的每个人都在其密钥库中拥有CA的公钥, 由仔细检查密钥指纹的系统管理员安装。 CA签署ACME的密钥 雇员。当他们安装彼此的密钥时,密钥库会隐含地信任它们,因为它们是 由可信密钥签名。

以下是模拟此过程的方法。
创建一个密钥库acmesoft.certs 生成密钥par并导出公钥:

代码视图:
keytool -genkeypair -keystore acmesoft.certs -alias acmeroot
keytool -exportcert -keystore acmesoft.certs -alias acmeroot -file acmeroot.cer

将公钥导出为"自签名"证书。然后将其添加到每个员工的密钥库中。

代码视图:
keytool -importcert -keystore cindy.certs -alias acmeroot -file acmeroot.cer

为了让Alice向Cindy和ACME Software的其他人发送消息,她需要携带她的证书 信息资源部门并签署。不幸的是,缺少此功能 keytool计划。在本书的配套代码中,我们提供了CertificateSigner类来填补空白。一个 ACME Software的授权工作人员将验证Alice的身份并生成签名证书 如下:

java CertificateSigner -keystore acmesoft.certs -alias acmeroot -infile alice.cer -outfile alice_signedby_acmeroot.cer

证书签名者程序必须能够访问ACME Software密钥库,并且工作人员必须知道 密钥库密码。显然,这是一项敏感的操作。 Alice将文件alice_signedby_acmeroot.cer文件提供给Cindy以及ACME Software中的任何其他人。 或者,ACME Software可以将文件存储在公司目录中。请记住,此文件包含Alice's 公钥和ACME软件声明该密钥真正属于Alice。 现在Cindy将签名证书导入她的密钥库:

代码视图: keytool -importcert -keystore cindy.certs -alias alice -file alice_signedby_acmeroot.cer

密钥库验证密钥是否已由密钥库中已存在的受信任根密钥签名。辛迪是 没有要求验证证书指纹。 一旦Cindy添加了根证书和经常发送她的文件的人的证书,她 再也不用担心密钥库了。

这是CertificateSigner程序的代码:

public class CertificateSigner
{
public static void main(String[] args)
{
  String ksname = null; // the keystore name
  String alias = null; // the private key alias
  String inname = null; // the input file name
  String outname = null; // the output file name
  for (int i = 0; i < args.length; i += 2)
  {
     if (args[i].equals("-keystore")) ksname = args[i + 1];
     else if (args[i].equals("-alias")) alias = args[i + 1];
     else if (args[i].equals("-infile")) inname = args[i + 1];
     else if (args[i].equals("-outfile")) outname = args[i + 1];
     else usage();
  }

  if (ksname == null || alias == null || inname == null || outname == null) usage();

  try
  {
     Console console = System.console();
     if (console == null) error("No console");
     char[] password = console.readPassword("Keystore password: ");
     KeyStore store = KeyStore.getInstance("JKS", "SUN");
     InputStream in = new FileInputStream(ksname);
     store.load(in, password);
     Arrays.fill(password, ' ');
     in.close();

     char[] keyPassword = console.readPassword("Key password for %s: ", alias);
     PrivateKey issuerPrivateKey = (PrivateKey) store.getKey(alias, keyPassword);
     Arrays.fill(keyPassword, ' ');

     if (issuerPrivateKey == null) error("No such private key");

            in = new FileInputStream(inname);

         CertificateFactory factory = CertificateFactory.getInstance("X.509");

         X509Certificate inCert = (X509Certificate) factory.generateCertificate(in);
         in.close();
         byte[] inCertBytes = inCert.getTBSCertificate();

     X509Certificate issuerCert = (X509Certificate) store.getCertificate(alias);
     Principal issuer = issuerCert.getSubjectDN();
     String issuerSigAlg = issuerCert.getSigAlgName();

     FileOutputStream out = new FileOutputStream(outname);

     X509CertInfo info = new X509CertInfo(inCertBytes);
     info.set(X509CertInfo.ISSUER, new CertificateIssuerName((X500Name) issuer));

     X509CertImpl outCert = new X509CertImpl(info);
     outCert.sign(issuerPrivateKey, issuerSigAlg);
     outCert.derEncode(out);

     out.close();
  }
  catch (Exception e)
  {
     e.printStackTrace();
  }
 }

 public static void error(String message)
 {
  System.out.println(message);
  System.exit(1);
 }

public static void usage()
{
  System.out.println("Usage: java CertificateSigner"
        + " -keystore keyStore -alias issuerKeyAlias"
        + " -infile inputFile -outfile outputFile");
  System.exit(1);
}
}

1 个答案:

答案 0 :(得分:1)

  

流程1按时间顺序

     

我将这个ME signed_cert提供给cindy

没有。 ME使用相同的别名将此签名证书导入其密钥库。

  

cindy导入ME signed_cert受信任证书,因为cindy之前已经导入了CA证书

没有。不必要的。

  

我用ME私钥(不是ME signed_cert)

签署了ME jar

正确,虽然区别是无效的,因为你只提供了包含两者的别名。

  

我把ME jar文件给cindy   cindy在ME jar上做了一个jarsigner验证

正确。

  

流程1问题   Cindy密钥库将具有ME signed_certs,其由ME公钥和CA签名组成。

没有。见上文。

  

cindy.jks上ME jar上的jarsigner验证显示没有找到密钥。

然后你没有正确签名。见上文。

  

我预计它会显示密钥,因为cindy.jks中的ME signed_cert具有带有CA私有签名的ME公钥,而ME jar文件是使用ME私钥签名的。

它并不需要。我不知道你找到的密钥是什么意思,但是Cindy没有私钥,也不需要它来验证JAR文件。实际上,她甚至不需要自己的KeyStore。证书链在JAR文件中。

  

过程2   正如流程1一样,但是:   我将返回的ME signed_certs从acmesoft(包含&gt; ME公钥和CA签名)导入ME jks   我使用jarsigner签署ME jar文件

     

处理2问题   签字后,小丑们投诉如下:

     

jarsigner:找不到证书链:primary_root。 primary_root必须引用包含私钥和相应公钥证书链的有效KeyStore密钥条目。

您没有正确导入签名证书。您必须使用与生成密钥对和CSR时相同的别名。这是签名证书与私钥相关联的唯一方式。