可預測的偽隨機數發生器 漏洞特征:PREDICTABLE_RANDOM在某些關鍵的安全環境中使用可預測的隨機數可能會導致漏洞,比如,當這個值被作為: csrf token;如果攻擊者可以預測csrf的token值的話,就可以發動csrf攻擊 重置密碼的token(通過郵件發送);如果重置密碼的tok ...
可預測的偽隨機數發生器
漏洞特征:PREDICTABLE_RANDOM
在某些關鍵的安全環境中使用可預測的隨機數可能會導致漏洞,比如,當這個值被作為:
- csrf token;如果攻擊者可以預測csrf的token值的話,就可以發動csrf攻擊
- 重置密碼的token(通過郵件發送);如果重置密碼的token被替換的話,那麼就會導致用戶賬戶被接管,因為攻擊者會猜測到重置密碼的鏈接。
- 其他包含秘密的信息
修複這個漏洞最快的方式是用強隨機數生成器( 比如:java.security.SecureRandom
)替換掉java.util.Random
有漏洞的代碼:
String generateSecretToken(){ 隨機r = new Random(); return Long.toHexString(r.nextLong()); }View Code
解決方案
import org.apache.commons.codec.binary.Hex; String generateSecretToken() { SecureRandom secRandom = new SecureRandom(); byte[] result = new byte[32]; secRandom.nextBytes(result); return Hex.encodeHexString(result); }View Code
引用:
Cracking Random Number Generators - Part 1 (http://jazzy.id.au)
CERT: MSC02-J. Generate strong random numbers
CWE-330: Use of Insufficiently Random Values
Predicting Struts CSRF Token (Example of real-life vulnerability and exploitation)
可預測的偽隨機數發生器(Scala)
漏洞特征:PREDICTABLE_RANDOM_SCALA
在某些關鍵的安全環境中使用可預測的隨機數可能會導致漏洞,比如,當這個值被作為:
- csrf token;如果攻擊者可以預測csrf的token值的話,就可以發動csrf攻擊
- 重置密碼的token(通過郵件發送);如果重置密碼的token被替換的話,那麼就會導致用戶賬戶被接管,因為攻擊者會猜測到重置密碼的鏈接。
- 其他包含秘密的信息
修複這個漏洞最快的方式是用強隨機數生成器( 比如:java.security.SecureRandom
)替換掉java.util.Random
有漏洞的代碼:
import scala.util.Random def generateSecretToken() { val result = Seq.fill(16)(Random.nextInt) return result.map("%02x" format _).mkString }View Code
解決方案:
import java.security.SecureRandom def generateSecretToken() { val rand = new SecureRandom() val value = Array.ofDim[Byte](16) rand.nextBytes(value) return value.map("%02x" format _).mkString }View Code
Cracking Random Number Generators - Part 1 (http://jazzy.id.au)
CERT: MSC02-J. Generate strong random numbers
CWE-330: Use of Insufficiently Random Values
Predicting Struts CSRF Token (Example of real-life vulnerability and exploitation)
沒有做任何安全檢查的servlet 參數
漏洞特征:SERVLET_PARAMETER
Servlet 會從各種函數中獲取到GET和POST的值。這些被獲取的值肯定是不安全的。在進入到敏感的api函數之前你可能需要驗證和過濾這些值:
- sql 查詢 (可能導致sql註入)
- 文件操作 ( 可能會導致目錄穿越 )
- 命令執行 ( 可能會導致命令註入 )
- html解析 (可能會導致xss)
- 其他的
引用:
CWE-20: Improper Input Validation
沒有做任何安全檢查Content-Type 頭
漏洞特征:SERVLET_CONTENT_TYPE
伺服器端程式通過客戶端收集http的Content-Type的值。這個值可能會影響影響應用的安全性
引用:
CWE-807: Untrusted Inputs in a Security Decision
沒有做任何安全檢查Hostname 頭
漏洞特征: SERVLET_SERVER_NAME
伺服器端程式通過客戶端收集http的hostname 的值。這個值可能會影響影響應用的安全性。ServletRequest.getServerName()
和 HttpServletRequest.getHeader("Host")
的行為很相似,都是從http頭部中獲取到host的值
GET /testpage HTTP/1.1
Host: www.example.com
[...]
View Code
預設情況下,web容器可能會直接將請求重定向到你的應用程式中。這就允許用戶把惡意的請求放入http的host頭中。我建議你不要信任來自客戶端的任何輸入。
引用:
CWE-807: Untrusted Inputs in a Security Decision
沒有做任何安全檢查的session cookie值
漏洞特征: SERVLET_SESSION_ID
HttpServletRequest.getRequestedSessionId()
( http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getRequestedSessionId() )函數返回cookie中JSESSIONID的值。這個值通常被session 管理器訪問,而不是開發者代碼。
傳遞給客戶端的值通常是字母數字( 例如:JSESSIONID=jp6q31lq2myn ),無論如何,這個值可以被客戶端改變,下麵的http請求展示了潛在的危險
GET /somePage HTTP/1.1 Host: yourwebsite.com User-Agent: Mozilla/5.0 Cookie: JSESSIONID=Any value of the user's choice!!??'''">View Code
像這樣,JSESSIONID應該僅被使用判斷是否與存在的session ID相匹配,如果不存在對應的session ID,那麼這個用戶就可能會是未授權用戶。此外, session ID的值應該從來不被記錄,如果記錄了,那麼日誌文件中就會包含有效的且在激活狀態的session IDs,這樣就會允許內部員工可以通過日誌記錄來劫持任意線上用戶。
引用:
OWASP: Session Management Cheat Sheet
CWE-20: Improper Input Validation
沒有做任何安全檢查的查詢字元串
漏洞特征: SERVLET_QUERY_STRING
查詢字元串是get請求中參數名和參數值的串聯,可以傳入預期之外的參數。 比如URL請求:/app/servlet.htm?a=1&b=2 ,查詢字元串就是a=1&b=2
通過函數 HttpServletRequest.getParameter() 接收每一個傳遞進來的參數的值,通過 HttpServletRequest.getQueryString() 這個函數獲取到的值應該被看做不安全的。你應該在查詢字元串進入敏感函數之前去充分的效驗和過濾它們。
引用:
CWE-20: Improper Input Validation
沒有做任何安全檢查的HTTP頭
漏洞特征:SERVLET_HEADER
http請求頭很容易會被用戶所修改。通常,不要假想請求來自於沒有被黑客修改的常規瀏覽器。我建議你,不要相信客戶端傳遞進來的http頭部值
引用:
CWE-807: Untrusted Inputs in a Security Decision
沒有做任何安全檢查的Referer值
漏洞特征:SERVLET_HEADER_REFERER
行為:
- 如果請求來自於惡意用戶,那麼Referer的值會是任意的情況。
- 如果請求來自於另一個安全的源(https),那麼Referer頭就是空的。
建議:
- 訪問控制不應該基於此標頭的值。
- csrf保護不應該僅基於此值。( 因為這個選項 )
引用:
CWE-807: Untrusted Inputs in a Security Decision
沒有做任何安全檢查的User-Agent值
漏洞特征: SERVLET_HEADER_USER_AGENT
"User-Agent" 很容易被客戶端偽造,不建議基於不同的User-Agent(比如爬蟲的UA)來適配不同的行為。
引用:
CWE-807: Untrusted Inputs in a Security Decision
潛在的cookie中包含敏感數據
漏洞特征: COOKIE_USAGE
存儲在客戶端中cookie的數據不應該包含敏感數據或者與session相關的數據。大多數情況下,敏感數據應該僅僅存儲在session中,並且通過通過用戶的session值去訪問。詳細請看HttpSession (HttpServletRequest.getSession())
客戶端cookie應該是比特定會話維持時間更長且獨立於特殊會話
引用:
CWE-315: Cleartext Storage of Sensitive Information in a Cookie
潛在的路徑穿越(文件讀取)
漏洞特征:PATH_TRAVERSAL_IN
一個文件被打開,然後讀取文件內容,這個文件名來自於一個輸入的參數。如果沒有過濾這個傳入的參數,那麼本地文件系統中任意文件都會被讀取。
這個規則識別潛在的路徑穿越漏洞。在許多場景中,用戶無法控制文件路徑,如果有工具報告了這個問題,那麼這個就是誤報
有漏洞代碼:
@GET @Path("/images/{image}") @Produces("images/*") public Response getImage(@javax.ws.rs.PathParam("image") String image) { File file = new File("resources/images/", image); //Weak point if (!file.exists()) { return Response.status(Status.NOT_FOUND).build(); } return Response.ok().entity(new FileInputStream(file)).build(); }View Code
解決方案:
import org.apache.commons.io.FilenameUtils; @GET @Path("/images/{image}") @Produces("images/*") public Response getImage(@javax.ws.rs.PathParam("image") String image) { File file = new File("resources/images/", FilenameUtils.getName(image)); //Fix if (!file.exists()) { return Response.status(Status.NOT_FOUND).build(); } return Response.ok().entity(new FileInputStream(file)).build(); }View Code
引用:
WASC: Path Traversal
OWASP: Path Traversal
CAPEC-126: Path Traversal
CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
潛在的路徑穿越(文件寫)
漏洞特征:PATH_TRAVERSAL_OUT
一個文件被打開,然後讀取文件內容,這個文件名來自於一個輸入的參數。如果沒有過濾這個傳入的參數,那麼本地文件系統中任意文件都會被修改。
這個規則識別潛在的路徑穿越漏洞。在許多場景中,用戶無法控制文件路徑,如果有工具報告了這個問題,那麼這個就是誤報
引用:
WASC: Path Traversal
OWASP: Path Traversal
CAPEC-126: Path Traversal
CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
潛在的路徑穿越(文件讀取)
漏洞特征:
SCALA_PATH_TRAVERSAL_IN
一個文件被打開,然後讀取文件內容,這個文件名來自於一個輸入的參數。如果沒有過濾這個傳入的參數,那麼本地文件系統中任意文件都會被讀取。
這個規則識別潛在的路徑穿越漏洞。在許多場景中,用戶無法控制文件路徑,如果有工具報告了這個問題,那麼這個就是誤報
有漏洞代碼:
def getWordList(value:String) = Action { if (!Files.exists(Paths.get("public/lists/" + value))) { NotFound("File not found") } else { val result = Source.fromFile("public/lists/" + value).getLines().mkString // Weak point Ok(result) } }View Code
解決方案:
import org.apache.commons.io.FilenameUtils; def getWordList(value:String) = Action { val filename = "public/lists/" + FilenameUtils.getName(value) if (!Files.exists(Paths.get(filename))) { NotFound("File not found") } else { val result = Source.fromFile(filename).getLines().mkString // Fix Ok(result) } }View Code
引用:
WASC: Path Traversal
OWASP: Path Traversal
CAPEC-126: Path Traversal
CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
潛在的命令註入
漏洞特征:COMMAND_INJECTION
高亮部分的api被用來執行系統命令,如果輸入這個api的數據沒有被過濾,那麼就會導致任意命令執行
有漏洞的代碼:
import java.lang.Runtime; Runtime r = Runtime.getRuntime(); r.exec("/bin/sh -c some_tool" + input);View Code
引用:
OWASP: Command Injection
OWASP: Top 10 2013-A1-Injection
CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
潛在的命令註入(Scala)
漏洞特征:COMMAND_INJECTION
高亮部分的api被用來執行系統命令,如果輸入這個api的數據沒有被過濾,那麼就會導致任意命令執行
有漏洞的代碼:
def executeCommand(value:String) = Action { val result = value.! Ok("Result:\n"+result) }View Code
引用:
OWASP: Command Injection
OWASP: Top 10 2013-A1-Injection
CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
文件類函數沒有過濾空字元
漏洞特征:WEAK_FILENAMEUTILS
一些文件類中方法沒有過濾空位元組(0x00)
如果空位元組被註入到文件名之中,如果這個文件被放進系統之中,那麼系統則只會讀取空字元之前的文件名,字元串就會被空字元截斷,甚至java本身也不能關註空字元或者處理這些特殊情況。操作系統的這一特性通常被用來繞過文件名驗證去訪問其他的文件(例如,尾碼是.log"的文件)。
給出兩點建議去修複這個問題:
- 升級到7 update 40 或者最近的版本,或者java 8 +,因為空位元組註入這個問題已經被這些版本的java所解決
- 要嚴格驗證用戶輸入的文件名是否是有效的(例如不能包含空字元,不能包含路徑字元)
如果你知道你使用的現有的java版本可以避免空字元註入問題,你可以忽略上面的問題。
引用:
WASC-28: Null Byte Injection
CWE-158: Improper Neutralization of Null Byte or NUL Character
證書管理器接受任何證書
漏洞特征: WEAK_TRUST_MANAGER
空的證書管理器通常可以更輕鬆的連接到沒有根證書的主機上。結果就是,就會更容易受到中間人攻擊,因為客戶端信任所有的證書。
一個證書管理器應該允許信任指定的一種證書(例如:基於信任庫)。下麵是一種可行的實現方法:
有漏洞的代碼:
class TrustAllManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { //Trust any client connecting (no certificate validation) } @Override public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { //Trust any remote server (no certificate validation) } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }View Code
解決方案(基於證書庫的證書管理器):
KeyStore ks = //Load keystore containing the certificates trusted SSLContext sc = SSLContext.getInstance("TLS"); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ks); sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),null);View Code
引用:
WASC-04: Insufficient Transport Layer Protection
CWE-295: Improper Certificate Validation
HostnameVerifier 接收任何簽名證書
漏洞規則:WEAK_HOSTNAME_VERIFIER
因為證書會被很多主機重覆使用,接收任意證書的HostnameVerifier經常被使用。結果就是,就會更容易受到中間人攻擊,因為客戶端信任所有的證書。
一個證書管理器應該允許信任指定的一種證書(例如:基於信任庫)。應該創建通配符證書,可以允許多個子域下證書。下麵是一種可行的實現方法:
有漏洞的代碼:
public class AllHosts implements HostnameVerifier { public boolean verify(final String hostname, final SSLSession session) { return true; } }View Code
解決方案(基於證書庫的證書管理器):
KeyStore ks = //Load keystore containing the certificates trusted SSLContext sc = SSLContext.getInstance("TLS"); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ks); sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),null);View Code
引用:
WASC-04: Insufficient Transport Layer Protection
CWE-295: Improper Certificate Validation
發現JAX-RS REST伺服器端
漏洞規則: JAXRS_ENDPOINT
這些函數是REST Web Service 的一部分(JSR311).
這個網站的安全性應該被分析。例如:
-
許可權認證,如果強制實施,就應該被測試 訪問控制,如果強制實施,就應該被測試 輸入應該被追蹤,因為可能會有潛在的漏洞 聊天程式應該使用SSL 如果伺服器支持存儲私人數據(例如,通過POST),應該調查它是否對csrf有防禦
View Code
引用:
OWASP: REST Assessment Cheat Sheet
OWASP: REST Security Cheat Sheet
OWASP: Web Service Security Cheat Sheet
OWASP: Cross-Site Request Forgery)
OWASP: CSRF Prevention Cheat Sheet
CWE-20: Improper Input Validation
發現Tapestry頁面
漏洞規則: TAPESTRY_ENDPOINT
在應用啟動的時候,Tapestry會被髮現。Tapestry應用的每一個頁面又後端java類和相關的Tapestry標記語言構成(a.tml 文件)。當請求到達的時候,GET/POST參數會被映射到後端的java類之中。映射可以使用fieldName完成:
[...] protected String input; [...]View Code
或者顯示註釋的定義:
...] @org.apache.tapestry5.annotations.Parameter protected String parameter1; @org.apache.tapestry5.annotations.Component(id = "password") private PasswordField passwordField; [...]View Code
這個頁面被映射到視圖中[/resources/package/PageName].tml.
在應用中的每一個Tapestry頁面應該被調查,確保所有的輸入都能被自動的映射,併在這些參數被使用之前都是有效的。
引用:
Apache Tapestry Home Page
CWE-20: Improper Input Validation
發現Wicket的web頁面
漏洞特征:WICKET_ENDPOINT
這個類代表一個Wicket web頁面。輸入的數據會被來自實例中的PageParameters讀取,然後把它們送入後端處理程式。當前頁面會被映射到視圖之中[/package/WebPageName].html.
在應用中的每一個Wicket頁面應該被調查,確保所有的輸入都能被自動的映射,併在這些參數被使用之前都是有效的。
引用:
Apache Wicket Home Page
CWE-20: Improper Input Validation
MD2, MD4 和 MD5都是脆弱的哈希函數
漏洞特征:WEAK_MESSAGE_DIGEST_MD5
不建議使用MD2, MD4 和 MD5這個摘要演算法。應該使用PBKDF2作為密碼的摘要演算法。
md5哈希演算法的安全性被嚴重損害。現已存在一種碰撞攻擊,這種攻擊可以用奔騰2.6 GHz 4核處理器在幾秒內碰撞出另一個哈希相同的字元串。進一步來說,還有選擇首碼碰撞攻擊(chosen-prefix collision attack ),這種攻擊能在一個小時之內找到兩個首碼相同的哈希,只要現有電腦的計算水平就可以達到。
"SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256:View Code
所有散列計算程式都支持這些哈希函數的使用。
NISI:通信傳輸:[傳輸中建議使用的加密演算法和密鑰長度](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf)
PBKDF的主要思想是減緩字典生成的時間或者增加攻擊者攻擊每一個密碼的時間。攻擊者會有一個密碼表去爆破PBKDF所使用的迭代計數器和salt。因為攻擊者必須花費大量的計算時間去嘗試破解每一個密碼,所以攻擊者很難用字典攻擊和爆破攻擊去獲得成功。
NISI:基於密碼的密鑰的加密建議
有漏洞的代碼:
MessageDigest md5Digest = MessageDigest.getInstance("MD5"); md5Digest.update(password.getBytes()); byte[] hashValue = md5Digest.digest();View Code
解決方案:
public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest()); gen.init(password.getBytes("UTF-8"), salt.getBytes(), 4096); return ((KeyParameter) gen.generateDerivedParameters(256)).getKey(); }View Code
解決方案(java 8 和之後的版本)
public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 4096, 256 * 8); SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); return f.generateSecret(spec).getEncoded(); }View Code
引用:
[1] On Collisions for MD5: Master Thesis by M.M.J. Stevens
[2] Chosen-prefix collisions for MD5 and applications: Paper written by Marc Stevens
Wikipedia: MD5
NIST: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths
NIST: Recommendation for Password-Based Key Derivation
Stackoverflow: Reliable implementation of PBKDF2-HMAC-SHA256 for Java
CWE-327: Use of a Broken or Risky Cryptographic Algorithm
SHA-1 是脆弱的哈希演算法
漏洞特征: WEAK_MESSAGE_DIGEST_SHA1
不建議使用SHA-1演算法去加密密碼、做數字簽名和其他用途。應該使用PBKDF2作為密碼的摘要演算法。
“SHA-1用於生成電子簽名:
SHA-1可能僅僅用於NIST指導的特殊協議的電子簽名的生成。但是在其他的應用中,SHA-1 不應該用於電子簽名
SHA-1用於電子簽名的驗證:
對於電子簽名的驗證,SHA-1可以被用於傳統應用
"SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256:
所有散列計算程式都支持這些哈希函數的使用。
NISI:通信傳輸:[傳輸中建議使用的加密演算法和密鑰長度](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf)
PBKDF的主要思想是減緩字典生成的時間或者增加攻擊者攻擊每一個密碼的時間。攻擊者會有一個密碼表去爆破PBKDF所使用的迭代計數器和salt。因為攻擊者必須花費大量的計算時間去嘗試破解每一個密碼,所以攻擊者很難用字典攻擊和爆破攻擊去獲得成功。
NISI:基於密碼的密鑰的加密建議
有漏洞的代碼:
MessageDigest sha1Digest = MessageDigest.getInstance("SHA1"); sha1Digest.update(password.getBytes()); byte[] hashValue = sha1Digest.digest(); byte[] hashValue = DigestUtils.getSha1Digest().digest(password.getBytes());View Code
解決方案:
public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest()); gen.init(password.getBytes("UTF-8"), salt.getBytes(), 4096); return ((KeyParameter) gen.generateDerivedParameters(256)).getKey(); }View Code
解決方案(java 8 及以後的版本)
public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 4096, 256 * 8); SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); return f.generateSecret(spec).getEncoded(); }View Code
引用:
Qualys blog: SHA1 Deprecation: What You Need to Know
Google Online Security Blog: Gradually sunsetting SHA-1
NIST: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths
NIST: Recommendation for Password-Based Key Derivation
Stackoverflow: Reliable implementation of PBKDF2-HMAC-SHA256 for Java
CWE-327: Use of a Broken or Risky Cryptographic Algorithm
DefaultHttpClient的預設構造函數與TLS 1.2不相容
漏洞特征: DEFAULT_HTTP_CLIENT
有漏洞的代碼:
HttpClient client = new DefaultHttpClient();
View Code
解決方案:
用建議的構造函數去升級你的代碼並且配置jvm中https.protocols選項,使其包含TLSv1.2:
使用SystemDefaultHttpClient 代替
-
示例代碼: HttpClient client = new SystemDefaultHttpClient(); 基於SSLSocketFactory類創建一個HttpClient,通過 getSystemSocketFactory()) 獲得一個SSLScoketFactory實例,用這個實例去初始化一個HttpClient 基於SSLConnectionSocketFactory類創建一個HttpClient,通過 getSystemSocketFactory()) 獲得一個SSLScoketFactory實例,用這個實例去初始化一個HttpClient 使用HttpClientBuilder,在調用build()之前調用useSystemProperties() 示例代碼: HttpClient client = HttpClientBuilder.create().useSystemProperties().build(); HttpClients,調用 createSystem()去創建一個實例 示例代碼: HttpClient client = HttpClients.createSystem();
View Code
引用:
Diagnosing TLS, SSL, and HTTPS
脆弱的SSLContext
漏洞特征: SSL_CONTEXT
有漏洞的代碼:
SSLContext.getInstance("SSL");View Code
解決方案:
用下麵的代碼升級你的代碼,並且配置jvm的https.protocols選項,使其包含TLSv1.2
SSLContext.getInstance("TLS");View Code
引用:
Diagnosing TLS, SSL, and HTTPS
習慣使用的信息摘要演算法
自己實現消息摘要演算法是不靠譜的。
NIST建議使用SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, or SHA-512/256。
“SHA-1用於生成電子簽名:
SHA-1可能僅僅用於NIST指導的特殊協議的電子簽名的生成。但是在其他的應用中,SHA-1 不應該用於電子簽名
SHA-1用於電子簽名的驗證:
對於電子簽名的驗證,SHA-1可以被用於傳統應用
"SHA-224, SHA-256, SHA-384,