很多人對JSSE組成部分的Key Tool 工具不太明白,希望本文能有幫助
科班出身的同學應該學過課程“密碼學”, 這門課詳細解釋了現代對稱加密的算法原理, 當時學的我雲裡霧裡。 直到現在使用過SSL加密才知道工程上用法是這樣的, 老師講的時候就不能帶一點工程實踐嗎? 簡單來說,對稱加密體系就是我有一段需要加密的字元, 我用私鑰加密之後變成了無意義的密文, 隻有用配對的公鑰才能對這個密文進行解密還原回來。
下圖是個簡單的示意,注意由于公私鑰是配對的,一般給資訊加密的人持有此密鑰對。
這套機制可以應用在網絡上電子商務常用的可信任站點的證書 驗證上,因為電子商務站點經常涉及到交易,是以客戶需要知道這個電子商務網站是真的,可信任的, 而不是一個一摸一樣的僞造網站,來釣魚騙你賬戶和密碼的。
簡單說一下這個證書驗證的過程:
點選一個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.>.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憑證進行比對。
下面語句可以建一個keystore 并且生成一個公私鑰對,并把公鑰生成為公鑰證書:
導入證書語句如下:
Java程式在SSL連接配接建立相關操作時都需要操作這個key store檔案,來取得自己的私鑰或者拿自己信任的證書,簡單流程如下:
以上講的是用戶端的流程,下面看一下Java的web伺服器Jetty的一些這方面的設定,同樣,Jetty也需要一個這個檔案,就儲存在Jetty目錄的/etc/keystore中。
再看下Jetty 9 的ssl配置檔案Jetty-ssl.xml:
<Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
<Set name="KeyStorePath"><Property name="jetty.home" default="." />/<Property name="jetty.keystore" default="etc/keystore"/></Set>
<Set name="KeyStorePassword"><Property name="jetty.keystore.password" default="OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"/></Set>
<Set name="KeyManagerPassword"><Property name="jetty.keymanager.password" default="OBF:1u2u1wml1z7s1z7a1wnl1u2g"/></Set>
<Set name="TrustStorePath"><Property name="jetty.home" default="." />/<Property name="jetty.truststore" default="etc/keystore"/></Set>
<Set name="TrustStorePassword"><Property name="jetty.truststore.password" default="OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"/></Set>
<Set name="EndpointIdentificationAlgorithm"></Set>
明确指明了keystore和truststore檔案的路徑,其實就是同一個名為keystore的檔案, 并指明了密碼,下面我們用他的密碼看一下keystore中儲存了什麼,但Jetty的這個密碼如果是OBF開頭的則說明密碼被混淆過,運作
得到這個keystore的實際明文密碼 storepwd,然後到jetty/etc目錄下檢視Jetty的keystore檔案中都存了什麼證書:
Jetty 9的 中,部分組裝SSLConext的代碼如下:
SSLContext建構需要keyManager 和trustManager,Manager來自 keystore檔案中儲存的Entries。
本文出自 “祝坤榮” 部落格,請務必保留此出處