天天看點

雜談X509證書, Java Keystore與Jetty

很多人對JSSE組成部分的Key Tool 工具不太明白,希望本文能有幫助

科班出身的同學應該學過課程“密碼學”, 這門課詳細解釋了現代對稱加密的算法原理, 當時學的我雲裡霧裡。 直到現在使用過SSL加密才知道工程上用法是這樣的, 老師講的時候就不能帶一點工程實踐嗎? 簡單來說,對稱加密體系就是我有一段需要加密的字元, 我用私鑰加密之後變成了無意義的密文, 隻有用配對的公鑰才能對這個密文進行解密還原回來。

下圖是個簡單的示意,注意由于公私鑰是配對的,一般給資訊加密的人持有此密鑰對。

雜談X509證書, Java Keystore與Jetty

這套機制可以應用在網絡上電子商務常用的可信任站點的證書 驗證上,因為電子商務站點經常涉及到交易,是以客戶需要知道這個電子商務網站是真的,可信任的, 而不是一個一摸一樣的僞造網站,來釣魚騙你賬戶和密碼的。

簡單說一下這個證書驗證的過程:

點選一個https的網站

浏覽器開始建立ssl連接配接

浏覽器請求該網站證書,該證書主要包含了公鑰,及網站用私鑰加密證書内容後的簽名資料

浏覽器用公鑰解密簽名資料,驗證該證書完整性

浏覽器根據簽名者的名字驗證證書鍊,反複進行直到比對到了浏覽器内自帶的可信任根CA機構

為了更直覺點, 以下是用java程式取出來的Google的證書,主要的内容包括:

版本(Version),主題(Subject),簽名算法(Signature Algorithm),有效日期(Validity),認證機構(Issuer),序列号(SerialNumber),公鑰資訊(Key)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

<code>[</code>

<code>  </code><code>Version: V3</code>

<code>  </code><code>Subject: CN=www.google.com, O=Google Inc, L=Mountain View, ST=California, C=US</code>

<code>  </code><code>Signature Algorithm: SHA1withRSA, OID =</code><code>1.2</code><code>.</code><code>840.113549</code><code>.</code><code>1.1</code><code>.</code><code>5</code>

<code>  </code><code>Key:  Sun RSA</code><code>public</code> <code>key,</code><code>2048</code> <code>bits</code>

<code>  </code><code>modulus:</code><code>21234013066307499395457251007591480564049457586531682634102688105320414778844675214782297227108785101225473929899552731501456168053582903590770359069026387607503146650068399613049641154687616403518890644657095548686866113952705014503928651307072537712940705497213473591529858208623561782445051685850298532560404133534066309955969883121384862800482489711770827176592928627367189401567119209235611091403472756628910838905587679781334745044724147912894428457975079919303874339456674143408932927112368761924943362190459243823969871830702191962312600960355323190050761278795233954274164962425829947843114462063705745562381</code>

<code>  </code><code>public</code> <code>exponent:</code><code>65537</code>

<code>  </code><code>Validity: [From: Wed Jul</code><code>02</code> <code>21</code><code>:</code><code>38</code><code>:</code><code>55</code> <code>CST</code><code>2014</code><code>,</code>

<code>               </code><code>To: Tue Sep</code><code>30</code> <code>08</code><code>:</code><code>00</code><code>:</code><code>00</code> <code>CST</code><code>2014</code><code>]</code>

<code>  </code><code>Issuer: CN=Google Internet Authority G2, O=Google Inc, C=US</code>

<code>  </code><code>SerialNumber: [    5b7fd907 7ce7148c]</code>

<code>Certificate Extensions:</code><code>8</code>

<code>[</code><code>1</code><code>]: ObjectId:</code><code>1.3</code><code>.</code><code>6.1</code><code>.</code><code>5.5</code><code>.</code><code>7.1</code><code>.</code><code>1</code> <code>Criticality=</code><code>false</code>

<code>AuthorityInfoAccess [</code>

<code>  </code><code>[</code>

<code>   </code><code>accessMethod: caIssuers</code>

<code>   </code><code>accessLocation: URIName: http:</code><code>//pki.google.com/GIAG2.crt</code>

<code>,</code>

<code>   </code><code>accessMethod: ocsp</code>

<code>   </code><code>accessLocation: URIName: http:</code><code>//clients1.google.com/ocsp</code>

<code>]</code>

<code>[</code><code>2</code><code>]: ObjectId:</code><code>2.5</code><code>.</code><code>29.35</code> <code>Criticality=</code><code>false</code>

<code>AuthorityKeyIdentifier [</code>

<code>KeyIdentifier [</code>

<code>0000</code><code>: 4A DD</code><code>06</code> <code>16</code> <code>1B BC F6</code><code>68</code>   <code>B5</code><code>76</code> <code>F5</code><code>81</code> <code>B6 BB</code><code>62</code> <code>1A  J......h.v....b.</code>

<code>0010</code><code>: BA 5A</code><code>81</code> <code>2F                                        .Z./</code>

<code>[</code><code>3</code><code>]: ObjectId:</code><code>2.5</code><code>.</code><code>29.19</code> <code>Criticality=</code><code>true</code>

<code>BasicConstraints:[</code>

<code>  </code><code>CA:</code><code>false</code>

<code>  </code><code>PathLen: undefined</code>

<code>[</code><code>4</code><code>]: ObjectId:</code><code>2.5</code><code>.</code><code>29.31</code> <code>Criticality=</code><code>false</code>

<code>CRLDistributionPoints [</code>

<code>  </code><code>[DistributionPoint:</code>

<code>     </code><code>[URIName: http:</code><code>//pki.google.com/GIAG2.crl]</code>

<code>]]</code>

<code>[</code><code>5</code><code>]: ObjectId:</code><code>2.5</code><code>.</code><code>29.32</code> <code>Criticality=</code><code>false</code>

<code>CertificatePolicies [</code>

<code>  </code><code>[CertificatePolicyId: [</code><code>1.3</code><code>.</code><code>6.1</code><code>.</code><code>4.1</code><code>.</code><code>11129.2</code><code>.</code><code>5.1</code><code>]</code>

<code>[]  ]</code>

<code>[</code><code>6</code><code>]: ObjectId:</code><code>2.5</code><code>.</code><code>29.37</code> <code>Criticality=</code><code>false</code>

<code>ExtendedKeyUsages [</code>

<code>  </code><code>serverAuth</code>

<code>  </code><code>clientAuth</code>

<code>[</code><code>7</code><code>]: ObjectId:</code><code>2.5</code><code>.</code><code>29.17</code> <code>Criticality=</code><code>false</code>

<code>SubjectAlternativeName [</code>

<code>  </code><code>DNSName: www.google.com</code>

<code>[</code><code>8</code><code>]: ObjectId:</code><code>2.5</code><code>.</code><code>29.14</code> <code>Criticality=</code><code>false</code>

<code>SubjectKeyIdentifier [</code>

<code>0000</code><code>:</code><code>79</code> <code>DF 1E A5 4C</code><code>46</code> <code>0D</code><code>45</code>   <code>EE</code><code>18</code> <code>41</code> <code>68</code> <code>F0</code><code>83</code> <code>CA 4F  y...LF.E..Ah...O</code>

<code>0010</code><code>: C7 2C B4 C2                                        .,..</code>

<code>  </code><code>Algorithm: [SHA1withRSA]</code>

<code>  </code><code>Signature:</code>

<code>0000</code><code>: 7E B3</code><code>33</code> <code>11</code> <code>DC</code><code>10</code> <code>16</code> <code>C2  </code><code>99</code> <code>A0</code><code>53</code> <code>BD</code><code>24</code> <code>03</code> <code>4D</code><code>79</code>  <code>..</code><code>3</code><code>.......S.$.My</code>

<code>0010</code><code>:</code><code>92</code> <code>A5</code><code>15</code> <code>61</code> <code>F1 4E C6 F6   C5</code><code>10</code> <code>BB D0 8D</code><code>70</code> <code>F6</code><code>53</code>  <code>...a.N.......p.S</code>

<code>0020</code><code>: AA FE</code><code>25</code> <code>EA</code><code>33</code> <code>39</code> <code>2F 9C   DA C2</code><code>69</code> <code>94</code> <code>A4</code><code>34</code> <code>1D</code><code>57</code>  <code>..%.</code><code>39</code><code>/...i..</code><code>4</code><code>.W</code>

<code>0030</code><code>: A7 E4 D5</code><code>75</code> <code>94</code> <code>03</code> <code>8B</code><code>61</code>   <code>86</code> <code>2A A6</code><code>82</code> <code>FA C9</code><code>43</code> <code>37</code>  <code>...u...a.*....C7</code>

<code>0040</code><code>:</code><code>28</code> <code>28</code> <code>F6 3F 0E DA</code><code>88</code> <code>42</code>   <code>74</code> <code>2E</code><code>79</code> <code>0C 3E D1 4E 2A  ((.?...Bt.y.&gt;.N*</code>

<code>0050</code><code>: C7</code><code>25</code> <code>D7 E1</code><code>44</code> <code>1A</code><code>30</code> <code>D1   C6</code><code>33</code> <code>F4 E4 4E 5E B7</code><code>78</code>  <code>.%..D.</code><code>0</code><code>..</code><code>3</code><code>..N^.x</code>

<code>0060</code><code>: C3 1D C2 BE</code><code>47</code> <code>0E 3D D3   CF</code><code>09</code> <code>74</code> <code>5C 7F</code><code>84</code> <code>C8</code><code>55</code>  <code>....G.=...t\...U</code>

<code>0070</code><code>: EA B0</code><code>00</code> <code>A2 7B CA D2 7A   B3</code><code>03</code> <code>1D</code><code>22</code> <code>AB</code><code>64</code> <code>D1 F6  .......z...".d..</code>

<code>0080</code><code>:</code><code>78</code> <code>5F</code><code>16</code> <code>D2</code><code>54</code> <code>7D</code><code>48</code> <code>9A   6B</code><code>27</code> <code>FD 2F BD</code><code>00</code> <code>1F 0A  x_..T.H.k'./....</code>

<code>0090</code><code>: A8</code><code>00</code> <code>7B CF 7B B8 F0</code><code>32</code>   <code>7A</code><code>25</code> <code>1E 6A 6B B2 A1</code><code>69</code>  <code>.......2z%.jk..i</code>

<code>00A0:</code><code>62</code> <code>1B B6 C0 6D</code><code>52</code> <code>6A D8   C6 C8 C3</code><code>68</code> <code>C8</code><code>28</code> <code>D5</code><code>75</code>  <code>b...mRj....h.(.u</code>

<code>00B0:</code><code>66</code> <code>C9</code><code>66</code> <code>12</code> <code>CB A5 0F</code><code>68</code>   <code>39</code> <code>3D D5</code><code>32</code> <code>90</code> <code>ED</code><code>13</code> <code>5B  f.f....h9=.</code><code>2</code><code>...[</code>

<code>00C0: C8 5A</code><code>89</code> <code>EB FA</code><code>74</code> <code>B7 F7   EC FB AB A2 8C</code><code>84</code> <code>BF</code><code>75</code>  <code>.Z...t.........u</code>

<code>00D0: 2A D0</code><code>23</code> <code>36</code> <code>DD 5B C3 1A   DB D9</code><code>06</code> <code>94</code> <code>C0</code><code>23</code> <code>BC</code><code>44</code>  <code>*.#</code><code>6</code><code>.[.......#.D</code>

<code>00E0: F2 F3 9A B0 FB</code><code>85</code> <code>1D F0  </code><code>48</code> <code>25</code> <code>2A 3B B9 9B</code><code>02</code> <code>DE  ........H%*;....</code>

<code>00F0: 4B</code><code>17</code> <code>4F</code><code>63</code> <code>7A</code><code>66</code> <code>0F 7E   3B</code><code>03</code> <code>31</code> <code>81</code> <code>86</code> <code>AA</code><code>57</code> <code>5D  K.Oczf..;.</code><code>1</code><code>...W]</code>

  關于這些資訊的更詳細解釋可以看規範RFC3280 , http://www.ietf.org/rfc/rfc3280.txt ,這裡就不扯得太遠了。上面的資訊跟下面規範裡的資訊是一一對應的

<a></a>

作業系統在出廠的時候已經預裝了CA的可信任證書,浏覽器在通過證書拿到證書鍊後,最終都會追溯到一個根路徑與作業系統自帶的出廠CA可信證書進行比對,如果成功了證明是可信任的證書。Chrome在windows系統下直接用windows系統自帶root證書進行驗證, 而Firefox則自己帶了一套可信證書,不與作業系統共用。

經過上面的解釋,大家直到JDK為什麼要弄一個keytool工具了, 這個工具就是用來生成key store檔案的,這個檔案儲存了兩種entry,一種是公私鑰對(key entries), 一種是公鑰證書(trusted certificate entries), 前者由于涉及到私鑰,保密要求更高。 key store 檔案儲存了java版的可信任證書,Java 的SSL用戶端要進行SSL握手時需要從對方證書的簽名者追溯到自己的可信任機構, 就是跟此檔案中儲存的CA憑證進行比對。

雜談X509證書, Java Keystore與Jetty

下面語句可以建一個keystore 并且生成一個公私鑰對,并把公鑰生成為公鑰證書:

導入證書語句如下:

Java程式在SSL連接配接建立相關操作時都需要操作這個key store檔案,來取得自己的私鑰或者拿自己信任的證書,簡單流程如下:

雜談X509證書, Java Keystore與Jetty

以上講的是用戶端的流程,下面看一下Java的web伺服器Jetty的一些這方面的設定,同樣,Jetty也需要一個這個檔案,就儲存在Jetty目錄的/etc/keystore中。

再看下Jetty 9 的ssl配置檔案Jetty-ssl.xml:

&lt;Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory"&gt;

&lt;Set name="KeyStorePath"&gt;&lt;Property name="jetty.home" default="." /&gt;/&lt;Property name="jetty.keystore" default="etc/keystore"/&gt;&lt;/Set&gt;

&lt;Set name="KeyStorePassword"&gt;&lt;Property name="jetty.keystore.password" default="OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"/&gt;&lt;/Set&gt;

&lt;Set name="KeyManagerPassword"&gt;&lt;Property name="jetty.keymanager.password" default="OBF:1u2u1wml1z7s1z7a1wnl1u2g"/&gt;&lt;/Set&gt;

&lt;Set name="TrustStorePath"&gt;&lt;Property name="jetty.home" default="." /&gt;/&lt;Property name="jetty.truststore" default="etc/keystore"/&gt;&lt;/Set&gt;

&lt;Set name="TrustStorePassword"&gt;&lt;Property name="jetty.truststore.password" default="OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"/&gt;&lt;/Set&gt;

&lt;Set name="EndpointIdentificationAlgorithm"&gt;&lt;/Set&gt;

明确指明了keystore和truststore檔案的路徑,其實就是同一個名為keystore的檔案, 并指明了密碼,下面我們用他的密碼看一下keystore中儲存了什麼,但Jetty的這個密碼如果是OBF開頭的則說明密碼被混淆過,運作

得到這個keystore的實際明文密碼  storepwd,然後到jetty/etc目錄下檢視Jetty的keystore檔案中都存了什麼證書:

Jetty 9的 中,部分組裝SSLConext的代碼如下:

SSLContext建構需要keyManager 和trustManager,Manager來自 keystore檔案中儲存的Entries。

本文出自 “祝坤榮” 部落格,請務必保留此出處