国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java應(yīng)用服務(wù)系統(tǒng)安全性,簽名和驗(yàn)簽淺析

這篇具有很好參考價(jià)值的文章主要介紹了Java應(yīng)用服務(wù)系統(tǒng)安全性,簽名和驗(yàn)簽淺析。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

1 前言

隨著互聯(lián)網(wǎng)的普及,分布式服務(wù)部署越來(lái)越流行,服務(wù)之間通信的安全性也是越來(lái)越值得關(guān)注。這里,筆者把應(yīng)用與服務(wù)之間通信時(shí),進(jìn)行的的安全性相關(guān),加簽驗(yàn)簽,進(jìn)行了一個(gè)簡(jiǎn)單的記錄。

2 安全性痛點(diǎn)

  • 網(wǎng)關(guān)服務(wù)接口,暴漏在公網(wǎng),被非法調(diào)用?
  • 增加了token安全驗(yàn)證,被抓包等其他手段攔截了token,token驗(yàn)證無(wú)效?
  • 參數(shù)被非法獲取,非法調(diào)用系統(tǒng)應(yīng)用的接口?
  • 接口參數(shù)被非法獲取后,同一個(gè)接口被重復(fù)多次非法調(diào)用?

3 技術(shù)選型

3.1 對(duì)稱(chēng)加密與非對(duì)稱(chēng)加密對(duì)比

  • 對(duì)稱(chēng)加密

    優(yōu)點(diǎn):加密速度快
    缺點(diǎn):密鑰管理分配困難,安全性較低

  • 非對(duì)稱(chēng)加密

    優(yōu)點(diǎn):安全性較高
    缺點(diǎn):加密速度慢

對(duì)稱(chēng)加密技術(shù)加密和解密使用的都是同一個(gè)密鑰,因此密鑰的管理非常困難,在分發(fā)密鑰的過(guò)程中,如果一方密鑰被截獲,那后面的通信就是不安全的

而非對(duì)稱(chēng)加密技術(shù)就很好的解決了這一問(wèn)題,非對(duì)稱(chēng)加密技術(shù)使用公鑰加密,私鑰加密。通信前把公鑰發(fā)布出去,私鑰只有自己保留,即便你的公鑰被攻擊者拿到,沒(méi)有私鑰,就無(wú)法進(jìn)行解密。

那有了非對(duì)稱(chēng)加密技術(shù),對(duì)稱(chēng)加密是不是就被淘汰了?當(dāng)然不是,因?yàn)榉菍?duì)稱(chēng)加密技術(shù)加解密比較慢,不適合對(duì)大量數(shù)據(jù)的加解密。

3.2 MD5是對(duì)稱(chēng)加密還是非對(duì)稱(chēng)加密?

  • 對(duì)稱(chēng)算法有哪些?

對(duì)稱(chēng)密碼算法又叫傳統(tǒng)密碼算法,也就是加密密鑰能夠從解密密鑰中推算出來(lái),反過(guò)來(lái)也成立。在大多數(shù)對(duì)稱(chēng)算法中,加密解密密鑰是相同的。常見(jiàn)的對(duì)稱(chēng)算法有:DES、IDEA、AES、SM1和SM4。

  • 非對(duì)稱(chēng)算法有哪些?

非對(duì)稱(chēng)密鑰也叫公開(kāi)密鑰加密,它是用兩個(gè)數(shù)學(xué)相關(guān)的密鑰對(duì)信息進(jìn)行編碼。在此系統(tǒng)中,其中一個(gè)密鑰叫公開(kāi)密鑰,可隨意發(fā)給期望同密鑰持有者進(jìn)行安全通信的人。公開(kāi)密鑰用于對(duì)信息加密。第二個(gè)密鑰是私有密鑰,屬于密鑰持有者,此人要仔細(xì)保存私有密鑰。密鑰持有者用私有密鑰對(duì)收到的信息進(jìn)行解密。常見(jiàn)的非對(duì)稱(chēng)算法有:RSA、ECC、SM2。

這個(gè)問(wèn)題有人吐槽過(guò),面試官竟然問(wèn)MD5是對(duì)稱(chēng)加密還是非對(duì)稱(chēng)加密?其實(shí),MD5不是加密算法,md5實(shí)際上既不是對(duì)稱(chēng)算法,也不是非對(duì)稱(chēng)加密算法。它是消息摘要(安全散列)算法。

  • 對(duì)稱(chēng)加密和非對(duì)稱(chēng)加密有哪些優(yōu)缺點(diǎn)?

    對(duì)稱(chēng)加密優(yōu)點(diǎn): 速度快,對(duì)稱(chēng)性加密通常在消息發(fā)送方需要加密大量數(shù)據(jù)時(shí)使用,具有算法公開(kāi)、計(jì)算量小、加密速度快、加密效率高的特點(diǎn)。對(duì)稱(chēng)加密算法的優(yōu)點(diǎn)在于加解密的高速度和使用長(zhǎng)密鑰時(shí)的解密性。

    對(duì)稱(chēng)加密的缺點(diǎn): 密鑰的管理和分發(fā)非常困難,不夠安全。在數(shù)據(jù)傳送前,發(fā)送方和接收方必須商定好密鑰,并且雙方都要保存好密鑰,如果一方的密鑰被泄露,那么加密信息也就不安全了,安全性得不到保證

    非對(duì)稱(chēng)加密優(yōu)點(diǎn):安全性更高,公鑰是公開(kāi)的,秘鑰是自己保存的,不需要將私鑰給別人

    非對(duì)稱(chēng)加密缺點(diǎn):加密和解密花費(fèi)時(shí)間長(zhǎng)、速度慢,只適合對(duì)少量數(shù)據(jù)進(jìn)行加密

  • MD5優(yōu)缺點(diǎn)

    MD5的優(yōu)點(diǎn):計(jì)算速度快,加密速度快,不需要密鑰;可以檢查文件的完整性,一旦文件被更改,MD5值會(huì)改變;防止被篡改,傳輸中一旦被篡改,計(jì)算出的MD5值也會(huì)改變;防止看到明文,公司存放密碼存放的是MD5值。

    MD5的缺點(diǎn):作為散列算法,經(jīng)過(guò)證實(shí),仍然會(huì)存在兩種不同數(shù)據(jù)會(huì)發(fā)生碰撞;MD5的安全性。將用戶(hù)的密碼直接MD5后存儲(chǔ)在數(shù)據(jù)庫(kù)中是不安全的。很多人使用的密碼是常見(jiàn)的組合,威脅者將這些密碼的常見(jiàn)組合進(jìn)行單向哈希,得到一個(gè)摘要組合,然后與數(shù)據(jù)庫(kù)中的摘要進(jìn)行比對(duì)即可獲得對(duì)應(yīng)的密碼。

綜上所述,md5是消息摘要算法,既不是對(duì)稱(chēng)算法也不是非對(duì)稱(chēng)算法。大部分情況下使用對(duì)稱(chēng)加密具有不錯(cuò)的安全性,如果需要分布式進(jìn)行密鑰分發(fā),那么就考慮使用非對(duì)稱(chēng)加密;如果不需要可逆計(jì)算,則考慮散列算法(md5)。

參考資料:https://www.eolink.com/news/post/28567.html

具體的加密算法可以參考另一篇博文:淺析對(duì)稱(chēng)加密與非對(duì)稱(chēng)加密算法
經(jīng)過(guò)分析,最終采用AES加密算法對(duì)參數(shù)進(jìn)行加密(有需要的話(huà)),加簽驗(yàn)簽采用RSA非對(duì)稱(chēng)加密算法。

3.3 RSA公鑰和私鑰區(qū)別,哪個(gè)加密哪個(gè)解密

公鑰和私鑰在一些銀行系統(tǒng)、第三方支付系統(tǒng)SDK中經(jīng)常會(huì)遇到,剛接觸公鑰私鑰的朋友們估計(jì)很難區(qū)分兩者的區(qū)別。

3.3.1 RSA公鑰和私鑰是什么

首先來(lái)說(shuō),RSA是一種非對(duì)稱(chēng)加密算法,它是由三位數(shù)學(xué)家(Rivest、Shamir、Adleman)設(shè)計(jì)出來(lái)的。非對(duì)稱(chēng)加密是相對(duì)于對(duì)稱(chēng)加密而言的。對(duì)稱(chēng)加密算法是指加密解密使用的是同一個(gè)秘鑰,而非對(duì)稱(chēng)加密是由兩個(gè)密鑰(公鑰、私鑰)來(lái)進(jìn)行加密解密的,由此可見(jiàn)非對(duì)稱(chēng)加密安全性更高。

公鑰顧名思義就是公開(kāi)的密鑰會(huì)發(fā)放給多個(gè)持有人,而私鑰是私有密碼往往只有一個(gè)持有人,公私鑰特性:

  • 公鑰與私鑰是成對(duì)出現(xiàn)的

  • 私鑰文件中包含了公鑰數(shù)據(jù),所以可以基于私鑰導(dǎo)出公鑰

  • 密鑰越長(zhǎng),越難破解,所以2048位密鑰比1024位密鑰要更安全

  • 公鑰和私鑰都是密鑰,被公開(kāi)的那個(gè)就是公鑰,沒(méi)有被公開(kāi)的那個(gè)就是私鑰

3.3.2 公鑰和私鑰都可用于加密和解密

公鑰和私鑰都可以用于加解密操作,用公鑰加密的數(shù)據(jù)只能由對(duì)應(yīng)的私鑰解密,反之亦然。雖說(shuō)兩者都可用于加密,但是不同場(chǎng)景使用不同的密鑰來(lái)加密,規(guī)則如下:

  • 私鑰用于簽名、公鑰用于驗(yàn)簽

    簽名和加密作用不同,簽名并不是為了保密,而是為了保證這個(gè)簽名是由特定的某個(gè)人簽名的,而不是被其它人偽造的簽名,所以私鑰的私有性就適合用在簽名用途上。

    私鑰簽名后,只能由對(duì)應(yīng)的公鑰解密,公鑰又是公開(kāi)的(很多人可持有),所以這些人拿著公鑰來(lái)解密,解密成功后就能判斷出是持有私鑰的人做的簽名,驗(yàn)證了身份合法性。

  • 公鑰用于加密、私鑰用于解密,這才能起到加密作用

    因?yàn)楣€是公開(kāi)的,很多人可以持有公鑰。若用私鑰加密,那所有持有公鑰的人都可以進(jìn)行解密,這是不安全的!

    若用公鑰加密,那只能由私鑰解密,而私鑰是私有不公開(kāi)的,只能由特定的私鑰持有人解密,保證的數(shù)據(jù)的安全性。

RSA算法可以總結(jié)為四句話(huà):公鑰加密、私鑰解密、私鑰簽名、公鑰驗(yàn)簽。加密是防止信息泄露,而簽名是為了防止信息被篡改。

java 驗(yàn)簽,Java基礎(chǔ)知識(shí),分布式專(zhuān)題,java,網(wǎng)絡(luò)安全,web安全

該內(nèi)容摘自:https://blog.csdn.net/weixin_37989267/article/details/126641628

4 請(qǐng)求頭參數(shù)

服務(wù)端提供簽名私鑰 private_key、應(yīng)用id app_id、商戶(hù)號(hào) merchant_no,另外,所有請(qǐng)求的接口,都需要添加請(qǐng)求頭Headers,8個(gè)參數(shù)如下:

名稱(chēng) 類(lèi)型 說(shuō)明 是否必填
method_name String 請(qǐng)求的方法名稱(chēng)
request_method String 請(qǐng)求方式(get or post)
merchant_no String 商戶(hù)號(hào),一個(gè)商戶(hù)可以有多個(gè)應(yīng)用
msg_id String 通訊唯一編號(hào)
app_id String 應(yīng)用系統(tǒng)唯一編號(hào)
sign_timestamp String 請(qǐng)求時(shí)應(yīng)用端簽名時(shí)的時(shí)間戳(毫秒單位),接入系統(tǒng)的時(shí)間誤差不能超過(guò)3分鐘,示例:1898098042342
api_gw_public_key String 網(wǎng)關(guān)公鑰key,通過(guò)該公鑰,才可以請(qǐng)求網(wǎng)關(guān)服務(wù)
request_sign String 簽名信息,用來(lái)驗(yàn)簽,通過(guò)簽名機(jī)制,防止應(yīng)用的請(qǐng)求參數(shù)被非法篡改,應(yīng)用系統(tǒng)必須保證相關(guān)私鑰不被泄露
  • 請(qǐng)求是head頭參數(shù)示例:

java 驗(yàn)簽,Java基礎(chǔ)知識(shí),分布式專(zhuān)題,java,網(wǎng)絡(luò)安全,web安全

注:postman自定義參數(shù),在Pre-request Script 輸入: pm.environment.set('sign_timestamp',new Date().getTime());
java 驗(yàn)簽,Java基礎(chǔ)知識(shí),分布式專(zhuān)題,java,網(wǎng)絡(luò)安全,web安全

5 簽名以及驗(yàn)簽機(jī)制

  • 原理
    請(qǐng)求接口的參數(shù)中添加sign簽名+時(shí)間戳(毫秒單位)
    具體實(shí)現(xiàn)原理:應(yīng)用端生成RSA私鑰加密簽名串,和當(dāng)前時(shí)間戳跟隨請(qǐng)求的參數(shù)一起發(fā)送到后臺(tái),后臺(tái)獲取簽名進(jìn)行RSA公鑰解密,然后獲取系統(tǒng)當(dāng)前時(shí)間戳和前端發(fā)送過(guò)來(lái)的時(shí)間戳做比較,如果兩者相差超過(guò)180s,則認(rèn)定為非法操作。這種方式既能保證防止請(qǐng)求重放,又能有效節(jié)省服務(wù)器資源

    注:應(yīng)用端調(diào)用服務(wù)端接口時(shí)的公鑰,必須為PKCS8格式的RSA 2048密鑰,該密鑰還必須經(jīng)過(guò)Base64轉(zhuǎn)換,服務(wù)端提供的API公鑰也遵從同樣標(biāo)準(zhǔn)。

  • 本文章涉及到的安全機(jī)制梳理如下:

    * 原有的token校驗(yàn),無(wú)法做到安全性,因?yàn)閠oken一般過(guò)期時(shí)間都很長(zhǎng),可以token多次訪問(wèn)
    * 原來(lái)可以直接簡(jiǎn)單的http調(diào)用,現(xiàn)在必須經(jīng)過(guò)一系列加簽過(guò)程才可以訪問(wèn)服務(wù)資源
    * 加簽時(shí)timestamp以日為單位,跨日時(shí)可能會(huì)驗(yàn)簽失敗,這里可以根據(jù)實(shí)際業(yè)務(wù)情況調(diào)整
    * api網(wǎng)關(guān)秘鑰校驗(yàn),只有有效的key才可以訪問(wèn)網(wǎng)關(guān)服務(wù)
    * 應(yīng)用端使用后端分配的私鑰(定期修改增加安全性)進(jìn)行加簽,后端進(jìn)行公鑰驗(yàn)簽,非對(duì)稱(chēng)加解密,增加了更高級(jí)別的安全性
    * 服務(wù)端分配商戶(hù)號(hào)和應(yīng)用編號(hào),保證唯一性
    * 應(yīng)用端加簽和服務(wù)端驗(yàn)簽,`時(shí)間戳不允許超過(guò)3min(可動(dòng)態(tài)調(diào)整)`,保證即使參數(shù)被盜,3min過(guò)期后仍然無(wú)法訪問(wèn)
    * 即使參數(shù)被非法獲取,也僅僅是那個(gè)接口極短時(shí)間內(nèi)有風(fēng)險(xiǎn),大大提高的系統(tǒng)的防攻擊特性
    

5.1 簽名

  • 系統(tǒng)采取的簽名算法
    SHA256WithRSA簽名算法,使用RSA非對(duì)稱(chēng)加密算法,可以采用應(yīng)用端 + 服務(wù)端雙重簽名的方式,來(lái)保證系統(tǒng)的安全性。

    Unlike symmetric encryption algorithms, asymmetric encryption algorithms require two keys: public key and private key. The public key and private key are a pair. If the data is encrypted with the public key, only the corresponding private key can be decrypted; If the data is encrypted with a private key, it can only be decrypted with the corresponding public key. Because encryption and decryption use two different keys, this algorithm is called asymmetric encryption algorithm

  • 簽名私鑰private_key、應(yīng)用idapp_id、商戶(hù)號(hào)merchant_no由服務(wù)端提供

5.2 加簽名思路

  • 參數(shù)數(shù)據(jù)是在應(yīng)用端,使用私鑰加密的,這里在服務(wù)端只能用相應(yīng)公鑰解密,即可驗(yàn)簽是否有效

  • 首先將method_name、request_method、merchant_no、msg_id、app_id、sign_timestamp拼接成一個(gè)字符串:

    getUserInfo?method_name=getUserInfo&request_method=get&merchant_no=6666XF20230306001&msg_id=666&app_id=10000000006666001&charset=UTF-8&format=json&sign_type=RSA2&timestamp=20230311
    
  • 把拼接后的字符串,按照ASCII排序

    getUserInfo?app_id=10000000006666001&charset=UTF-8&format=json&merchant_no=6666XF20230306001&method_name=getUserInfo&msg_id=666&request_method=get&sign_type=RSA2&timestamp=20230311
    

    注:ASCII碼的值從?到?為數(shù)字、?寫(xiě)英?字母、?寫(xiě)英?字母。48~57為0到9?個(gè)阿拉伯?dāng)?shù)字,65~90為26個(gè)?寫(xiě)英?字母,97~122號(hào)為26個(gè)?寫(xiě)英?字母。

  • 對(duì)私鑰進(jìn)行Base64加密

  • 對(duì)以上字符串進(jìn)行SHA256WithRSA簽名算法,運(yùn)算之后得到:

    VN2O+0Kgf9SSQf36BhUo6EqvMcKPlRHEm+6TWBqqQxCXmW5a88NYnVafItEBvWBajY8nR+8w9zhpNrCZZ2dHyg0umPZSDi6cDQL/zVX15fwvZlMRnccNHnMJ4QfDuybEN4NGWUDsOWXiEvlAzTA3/QYrRWivXpyrKS9xlA/CqTOvZIdwlcyJEokGHP55aMrJCfJuVdmKI6oqkPMpNvwHe/fQHi0krhkOJw7aa97WJ0tptqdpmnANz/lvCEvFBmvUIMVFtjpEutPTRSAL1miDZeKHdfPlUIMN0G/qoTdSyFF4yh0Nvk0rSvGd0/tVSxDUBE5sLhbjM5K+gLpo2iOQGQ==
    
  • 最后,將VsMiLe6字符串,添加到sign開(kāi)頭處,再次增加安全性,最后得到:

    VsMiLe6VN2O+0Kgf9SSQf36BhUo6EqvMcKPlRHEm+6TWBqqQxCXmW5a88NYnVafItEBvWBajY8nR+8w9zhpNrCZZ2dHyg0umPZSDi6cDQL/zVX15fwvZlMRnccNHnMJ4QfDuybEN4NGWUDsOWXiEvlAzTA3/QYrRWivXpyrKS9xlA/CqTOvZIdwlcyJEokGHP55aMrJCfJuVdmKI6oqkPMpNvwHe/fQHi0krhkOJw7aa97WJ0tptqdpmnANz/lvCEvFBmvUIMVFtjpEutPTRSAL1miDZeKHdfPlUIMN0G/qoTdSyFF4yh0Nvk0rSvGd0/tVSxDUBE5sLhbjM5K+gLpo2iOQGQ==
    

5.3 驗(yàn)簽思路

使用原有的請(qǐng)求入?yún)?,以及傳遞來(lái)的sign進(jìn)行公鑰解密,如果解密成功,就說(shuō)明驗(yàn)簽通過(guò),否則驗(yàn)簽失敗。

注:如果使用公鑰加密,則需要私鑰進(jìn)行解密,是雙向的。

6 功能核心代碼實(shí)現(xiàn)

6.1 SDK核心代碼

6.1.1 SmileConstants常量類(lèi)

/**
 * icbc.com.cn Inc.
 * Copyright (c) 2004-2016 All Rights Reserved.
 */
package cn.smilehappiness.security.constant;

/**
 * <p>
 * SmileConstants
 * <p/>
 *
 * @author
 * @Date 2023/3/6 19:30
 */
public class SmileConstants {

    public static final String SIGN_TYPE = "sign_type";

    public static final String SIGN_TYPE_RSA = "RSA";

    public static final String SIGN_TYPE_RSA2 = "RSA2";

    public static final String SIGN_TYPE_SM2 = "SM2";

    public static final String SIGN_TYPE_CA = "CA";

    public static final String SIGN_TYPE_SM = "SM";

    public static final String SIGN_TYPE_EM = "EM";

    public static final String SIGN_TYPE_EM_SM = "EM-SM";

    public static final String SIGN_SHA1RSA_ALGORITHMS = "SHA1WithRSA";

    public static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";

    public static final String ENCRYPT_TYPE_AES = "AES";

    public static final String METHOD_NAME = "method_name";

    public static final String REQUEST_METHOD = "request_method";

    public static final String MERCHANT_NO = "merchant_no";

    public static final String APP_ID = "app_id";

    public static final String SIGN_TIMESTAMP = "sign_timestamp";

    public static final String API_GW_PUBLIC_KEY = "api_gw_public_key";

    public static final String REQUEST_SIGN = "request_sign";

    public static final String FORMAT = "format";

    public static final String TIMESTAMP = "timestamp";

    public static final String SIGN = "sign";

    public static final String APP_AUTH_TOKEN = "app_auth_token";

    public static final String CHARSET = "charset";

    public static final String NOTIFY_URL = "notify_url";

    public static final String RETURN_URL = "return_url";

    public static final String ENCRYPT_TYPE = "encrypt_type";

    public static final String BIZ_CONTENT_KEY = "biz_content";

    /**
     * Default time format
     **/
    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    public static final String YYYY_MM_DD = "yyyyMMdd";

    /**
     * Date Default time zone
     **/
    public static final String DATE_TIMEZONE = "GMT+8";

    /**
     * UTF-8 character set
     **/
    public static final String CHARSET_UTF8 = "UTF-8";

    /**
     * GBK character set
     **/
    public static final String CHARSET_GBK = "GBK";

    /**
     * JSON  Format
     */
    public static final String FORMAT_JSON = "json";

    /**
     * XML  Format
     */
    public static final String FORMAT_XML = "xml";

    public static final String CA = "ca";

    public static final String PASSWORD = "password";

    public static final String RESPONSE_BIZ_CONTENT = "response_biz_content";

    /**
     * Message unique number
     **/
    public static final String MSG_ID = "msg_id";

    /**
     * sdk The version number in the headerkey
     */
    public static final String VERSION_HEADER_NAME = "APIGW-VERSION";

    /**
     * sdk Region number, for overseas institutions
     */
    public static final String ZONE_NO = "Zone-No";

    /**
     * Request type
     */
    public static final String REQUEST_Type = "Request-Type";

    /**
     * For em-type signatures, send a request to CICC Cryptography
     */
    public static final String EM_CFCA = "CFCA";

    /**
     * For em-type signature, send a request to the NC client
     */
    public static final String EM_NC = "NC";

    /**
     * Refined information
     */
    public static final String REFINE_INFO = "Apirefined-Info";

}

6.1.2 SmileClient類(lèi)

package cn.smilehappiness.security.api.client;

import cn.smilehappiness.security.constant.SmileConstants;
import cn.smilehappiness.security.dto.BaseRequest;
import cn.smilehappiness.security.utils.AesCryptUtil;
import cn.smilehappiness.security.utils.SecurityStringUtil;
import cn.smilehappiness.security.utils.SmileHashMap;
import cn.smilehappiness.security.utils.SmileSignatureUtil;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * <p>
 * smile client base deal
 * <p/>
 *
 * @author
 * @Date 2023/3/7 11:08
 */
public class SmileClient {

    private static final Logger logger = LoggerFactory.getLogger(SmileClient.class);

    protected String apiPublicKey;
    protected String merchantNo;
    protected String appId;
    protected String signType = SmileConstants.SIGN_TYPE_RSA;
    protected String privateKey;
    protected String publicKey;
    protected String charset = SmileConstants.CHARSET_UTF8;
    protected String format = SmileConstants.FORMAT_JSON;
    protected String encryptType;
    protected String encryptKey;

    public SmileClient() {

    }

    public SmileClient(String apiPublicKeyParam, String appId, String merchantNo, String signType, String privateKey, String publicKey, String charset, String format, String encryptType, String encryptKey) {
        this.apiPublicKey = apiPublicKeyParam;
        this.appId = appId;
        this.merchantNo = merchantNo;
        this.signType = signType;
        this.privateKey = privateKey;
        this.publicKey = publicKey;
        this.charset = charset;
        this.format = format;
        this.encryptType = encryptType;
        this.encryptKey = encryptKey;
    }

    public SmileClient(String apiPublicKeyParam, String appId, String merchantNo, String privateKey) {
        this(apiPublicKeyParam, appId, merchantNo, SmileConstants.SIGN_TYPE_RSA, privateKey, null, SmileConstants.CHARSET_UTF8, SmileConstants.FORMAT_JSON, null, null);
    }

    /**
     * <p>
     * rsa,rsa2,four params
     * <p/>
     *
     * @param apiPublicKeyParam
     * @param appId
     * @param signType
     * @param privateKey
     * @return
     * @Date 2023/3/7 11:08
     */
    public SmileClient(String apiPublicKeyParam, String appId, String merchantNo, String signType, String privateKey) {
        this(apiPublicKeyParam, appId, merchantNo, signType, privateKey, null, SmileConstants.CHARSET_UTF8, SmileConstants.FORMAT_JSON, null, null);
    }

    /**
     * <p>
     * check sign,five params
     * <p/>
     *
     * @param apiPublicKeyParam
     * @param appId
     * @param signType
     * @param privateKey
     * @return
     * @Date 2023/3/8 15:40
     */
    public SmileClient(String apiPublicKeyParam, String appId, String merchantNo, String signType, String privateKey, String publicKey) {
        this(apiPublicKeyParam, appId, merchantNo, signType, privateKey, publicKey, SmileConstants.CHARSET_UTF8, SmileConstants.FORMAT_JSON, null, null);
    }

    /**
     * <p>
     * six params -AES encrypt
     * <p/>
     *
     * @param apiPublicKeyParam
     * @param appId
     * @param signType
     * @param privateKey
     * @param encryptType
     * @param encryptKey
     * @return
     * @Date 2023/3/8 10:19
     */
    public SmileClient(String apiPublicKeyParam, String appId, String merchantNo, String signType, String privateKey, String encryptType, String encryptKey) {
        this(apiPublicKeyParam, appId, merchantNo, signType, privateKey, null, SmileConstants.CHARSET_UTF8, SmileConstants.FORMAT_JSON, encryptType, encryptKey);
    }

    public SmileClient(String apiPublicKeyParam, String appId, String merchantNo, String signType, String privateKey, String publicKey, String encryptType, String encryptKey) {
        this(apiPublicKeyParam, appId, merchantNo, signType, privateKey, publicKey, SmileConstants.CHARSET_UTF8, SmileConstants.FORMAT_JSON, encryptType, encryptKey);
    }

    private boolean checkApiPublicKeyLegal(String apiPublicKeyParam) {
        if (StringUtils.isBlank(apiPublicKeyParam) || !apiPublicKey.equals(apiPublicKeyParam)) {
            throw new RuntimeException("apiPublicKey param [" + apiPublicKeyParam + "] is unLegal");
        }

        return true;
    }

    /**
     * <p>
     * prepare params
     * <p/>
     *
     * @param request
     * @return cn.smilehappiness.security.utils.IcbcHashMap
     * @Date 2023/3/7 13:56
     */
    public SmileHashMap prepareParams(BaseRequest<?> request) {
        SmileHashMap params = new SmileHashMap();
        String strToSign = this.prepareParamStr(request, params);
        logger.info("addSign strToSign: {}", strToSign);

        if (signType.equals(SmileConstants.SIGN_TYPE_RSA) || signType.equals(SmileConstants.SIGN_TYPE_RSA2)) {
            String signedStr = SmileSignatureUtil.sign(strToSign, signType, privateKey, charset);
            params.put(SmileConstants.SIGN, signedStr);
        } else {
            // Other signature types
            logger.error("signType {} is not supported", signType);
            throw new RuntimeException("signType " + signType + " is not supported");
        }

        return params;
    }

    /**
     * <p>
     * prepare param str
     * <p/>
     *
     * @param request
     * @param params
     * @return java.lang.String
     * @Date 2023/3/8 16:34
     */
    private String prepareParamStr(BaseRequest<?> request, SmileHashMap params) {
        Map<String, String> extraParams = request.getExtraParameters();
        if (extraParams != null) {
            params.putAll(extraParams);
        }

        //appId Is the public variable of the class
        params.put(SmileConstants.METHOD_NAME, request.getMethodName());
        params.put(SmileConstants.REQUEST_METHOD, StringUtils.lowerCase(request.getRequestMethod()));
        params.put(SmileConstants.MERCHANT_NO, merchantNo);
        params.put(SmileConstants.APP_ID, appId);
        params.put(SmileConstants.MSG_ID, request.getMsgId());
        params.put(SmileConstants.SIGN_TYPE, signType);
        params.put(SmileConstants.CHARSET, charset);
        params.put(SmileConstants.FORMAT, format);

        try {
            // Get the timestamp, where you can achieve a higher level of control over the time dimension
            long timestamp = System.currentTimeMillis();
            DateFormat df = new SimpleDateFormat(SmileConstants.YYYY_MM_DD);
            df.setTimeZone(TimeZone.getTimeZone(SmileConstants.DATE_TIMEZONE));
            //time error is within 3 minutes, gateway control,this only 1d validity
            params.put(SmileConstants.TIMESTAMP, df.format(new Date(timestamp)));
        } catch (Exception exception) {
            exception.printStackTrace();
        }

        // Core content parameters need to be encrypted
        String bizContentStr = buildBizContentStr(request);
        if (request.isEncryptFlag()) {
            if (SecurityStringUtil.areEmpty(encryptType, encryptKey)) {
                logger.error("request need be encrypted, encrypt type and encrypt key can not be null");
                throw new RuntimeException("request need be encrypted, encrypt type and encrypt key can not be null");
            }

            if (bizContentStr != null) {
                params.put(SmileConstants.ENCRYPT_TYPE, encryptType);
                params.put(SmileConstants.BIZ_CONTENT_KEY, AesCryptUtil.encryptContent(bizContentStr, encryptType, encryptKey, charset));
            }

        } else {
            // Do not encrypt, fill in the requestParam field
            params.put(SmileConstants.BIZ_CONTENT_KEY, bizContentStr);
        }

        // Sort by rule
        return this.buildOrderedSignStr(request.getMethodName(), params);
    }

    /**
     * <p>
     * build biz content str
     * <p/>
     *
     * @param request
     * @return java.lang.String
     * @Date 2023/3/7 13:43
     */
    protected String buildBizContentStr(BaseRequest<?> request) {
        if (ObjectUtils.isEmpty(request.getBizContent())) {
            return null;
        }

        if (this.format.equals(SmileConstants.FORMAT_JSON)) {
            return JSON.toJSONString(request.getBizContent());
        } else {
            logger.error("only support json format, current format is not supported, format: {}", this.format);
            throw new RuntimeException("only support json format, current format is not supported, format: " + this.format);
        }
    }

    /**
     * <p>
     * build ordered sign str
     * <p/>
     *
     * @param methodName
     * @param params
     * @return java.lang.String
     * @Date 2023/3/7 11:25
     */
    private String buildOrderedSignStr(String methodName, Map<String, String> params) {
        Map<String, String> sortedMap = new TreeMap();
        sortedMap.putAll(params);
        Set<Map.Entry<String, String>> entries = sortedMap.entrySet();
        boolean hasParam = false;
        StringBuilder sb = new StringBuilder(methodName);
        sb.append("?");
        Iterator var6 = entries.iterator();

        while (var6.hasNext()) {
            Map.Entry<String, String> entry = (Map.Entry) var6.next();
            String name = entry.getKey();
            String value = entry.getValue();
            if (SecurityStringUtil.areNotEmpty(name, value)) {
                if (hasParam) {
                    sb.append("&");
                } else {
                    hasParam = true;
                }

                sb.append(name).append("=").append(value);
            }
        }

        return sb.toString();
    }

    /**
     * <p>
     * signCheck
     * <p/>
     *
     * @param request
     * @param signStr
     * @return T
     * @Date 2023/3/8 13:29
     */
    public <T> T signCheck(BaseRequest<T> request, String signStr) {
        if (StringUtils.isBlank(signStr)) {
            throw new RuntimeException("sign check fail, signStr param is null");
        }

        //check api public key legal
        this.checkApiPublicKeyLegal(request.getApiGwPublicKey());

        SmileHashMap params = new SmileHashMap();
        String strToSign = this.prepareParamStr(request, params);
        logger.info("signCheck strToSign: {}", strToSign);

        int indexOfSignStart = SmileSignatureUtil.SIGN_PREFIX.length();
        String sign = signStr.substring(indexOfSignStart);
        boolean passed = SmileSignatureUtil.verifySign(strToSign, this.signType, this.publicKey, this.charset, sign);
        if (!passed) {
            logger.error("sign verify not passed, please check");
            throw new RuntimeException("sign verify not passed, please check");
        }

        if (!request.isEncryptFlag()) {
            return null;
        }

        // The signature is base64 encoded, and no comma will appear
        String startKey = StringUtils.join(SmileConstants.BIZ_CONTENT_KEY, "=");
        int indexOfStart = strToSign.lastIndexOf(startKey);
        int indexOfEnd = strToSign.lastIndexOf("&charset");
        String bizContentStr = strToSign.substring(indexOfStart, indexOfEnd).replace(startKey, "");
        String bizContentDecryptResult = AesCryptUtil.decryptContent(bizContentStr, this.encryptType, this.encryptKey, this.charset);
        return (T) JSON.parse(bizContentDecryptResult);
    }

}

6.1.3 簽名工具類(lèi)

package cn.smilehappiness.security.utils;

import cn.smilehappiness.security.constant.SmileConstants;
import cn.smilehappiness.security.utils.crypt.RSAUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;

/**
 * <p>
 * smile signature util
 * <p/>
 *
 * @author
 * @Date 2023/3/7 14:04
 */
public class SmileSignatureUtil {

    private static final Logger logger = LoggerFactory.getLogger(SmileSignatureUtil.class);
    public static final String SIGN_PREFIX = "VsMiLe6";

    private SmileSignatureUtil() {

    }

    public static String sign(String content, String signType, String privateKey, String charset) {
        return sign(content, signType, privateKey, charset, null);
    }

    /**
     * <p>
     * sign
     * <p/>
     *
     * @param content
     * @param signType
     * @param privateKey
     * @param charset
     * @param password
     * @return java.lang.String
     * @Date 2023/3/7 14:15
     */
    public static String sign(String content, String signType, String privateKey, String charset, String password) {
        try {
            byte[] contentBytes = content.getBytes(charset);
            if (signType.equals(SmileConstants.SIGN_TYPE_RSA)) {
                String signStr = RSAUtil.sign(contentBytes, Base64.decodeBase64(privateKey), SmileConstants.SIGN_SHA1RSA_ALGORITHMS);
                return StringUtils.join(SIGN_PREFIX, signStr);
            } else if (signType.equals(SmileConstants.SIGN_TYPE_RSA2)) {
                String signStr = RSAUtil.sign(contentBytes, Base64.decodeBase64(privateKey), SmileConstants.SIGN_SHA256RSA_ALGORITHMS);
                return StringUtils.join(SIGN_PREFIX, signStr);
            }

            logger.error("not support signType");
            throw new RuntimeException("not support signType.");
        } catch (UnsupportedEncodingException e) {
            logger.error("get content charset exception, content: {} , charset:{} ,error info: {}", content, charset, e);
            throw new RuntimeException("get content charset exception. content: " + content + " charset: " + charset + e);
        } catch (Exception e) {
            logger.error("sign exception.", e);
            throw new RuntimeException("sign exception." + e);
        }

    }

    /**
     * <p>
     * verify sign
     * <p/>
     *
     * @param content
     * @param signType
     * @param publicKey
     * @param charset
     * @param sign
     * @return boolean
     * @Date 2023/3/7 14:15
     */
    public static boolean verifySign(String content, String signType, String publicKey, String charset, String sign) {
        try {
            byte[] contentBytes = content.getBytes(charset);
            if (signType.equals(SmileConstants.SIGN_TYPE_RSA)) {
                return RSAUtil.verify(contentBytes, Base64.decodeBase64(publicKey), sign, SmileConstants.SIGN_SHA1RSA_ALGORITHMS);
            } else if (signType.equals(SmileConstants.SIGN_TYPE_RSA2)) {
                return RSAUtil.verify(contentBytes, Base64.decodeBase64(publicKey), sign, SmileConstants.SIGN_SHA256RSA_ALGORITHMS);
            }

            logger.error("not support signType.");
            throw new RuntimeException("not support signType.");
        } catch (UnsupportedEncodingException e) {
            logger.error("get content charset exception. content: " + content + " charset: " + charset, e);
            throw new RuntimeException("get content charset exception. content: " + content + " charset: " + charset + e);
        } catch (Exception e) {
            logger.error("sign verify exception.", e);
            throw new RuntimeException("sign verify exception." + e);
        }
    }

}

6.2 加簽代碼示例

	@Test
    public void testAddSign() {
        BaseRequest<Map<String, Object>> request = new BaseRequest<>();
        //sign param
        request.setMethodName("getUserInfo");
        request.setRequestMethod("get");
        request.setMerchantNo("6666XF20230306001");
        request.setAppId("10000000006666001");
        request.setMsgId("666");
        request.setSignTimestamp(System.currentTimeMillis());
        request.setApiGwPublicKey(smileSecurityConfig.getApiGwPublicKey());

        SmileClient client = new SmileClient(smileSecurityConfig.getApiGwPublicKey(), smileSecurityConfig.getAppId(), smileSecurityConfig.getMerchantNo(), SmileConstants.SIGN_TYPE_RSA2, smileSecurityConfig.getPrivateKey());
        SmileHashMap smileHashMap = client.prepareParams(request);
        System.out.println(JSON.toJSONString(smileHashMap));
    }

6.3 驗(yàn)簽代碼示例

package com.itn.idn.gateway.security;

import cn.smilehappiness.security.api.client.SmileClient;
import cn.smilehappiness.security.config.SmileSecurityConfig;
import cn.smilehappiness.security.constant.SmileConstants;
import cn.smilehappiness.security.dto.BaseRequest;
import com.alibaba.fastjson.JSON;
import com.itn.idn.gateway.ErrorService;
import com.itn.idn.gateway.enums.GatewayExceptionEnum;
import com.itn.idn.gateway.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.Map;

/**
 * <p>
 * api security interceptor
 * <p/>
 *
 * @author
 * @Date 2023/3/10 17:40
 */
@Component
@RefreshScope
@ConfigurationProperties("security.config")
public class ApiSecurityInterceptor implements GlobalFilter, Ordered {

    private final Logger logger = LoggerFactory.getLogger(ApiSecurityInterceptor.class);
    private final long ALLOW_INTERVAL_TIMESTAMP = 180000L;

    @Autowired
    private ErrorService errorService;
    @Autowired
    private SmileSecurityConfig smileSecurityConfig;

    private String[] skipAuthUrls;

    public String[] getSkipAuthUrls() {
        return skipAuthUrls;
    }

    public void setSkipAuthUrls(String[] skipAuthUrls) {
        this.skipAuthUrls = skipAuthUrls;
    }

    /**
     * sign verify filter
     *
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String url = exchange.getRequest().getURI().getPath();
        // Skip paths that do not require validation
        if (StringUtils.matches(url, Arrays.asList(skipAuthUrls))) {
            return chain.filter(exchange);
        }

        String methodName = exchange.getRequest().getHeaders().getFirst(SmileConstants.METHOD_NAME);
        String requestMethod = exchange.getRequest().getHeaders().getFirst(SmileConstants.REQUEST_METHOD);
        String merchantNo = exchange.getRequest().getHeaders().getFirst(SmileConstants.MERCHANT_NO);
        String appId = exchange.getRequest().getHeaders().getFirst(SmileConstants.APP_ID);
        String msgId = exchange.getRequest().getHeaders().getFirst(SmileConstants.MSG_ID);
        String signTimestamp = exchange.getRequest().getHeaders().getFirst(SmileConstants.SIGN_TIMESTAMP);
        String apiGwPublicKey = exchange.getRequest().getHeaders().getFirst(SmileConstants.API_GW_PUBLIC_KEY);
        String requestSign = exchange.getRequest().getHeaders().getFirst(SmileConstants.REQUEST_SIGN);

        //head need params
        BaseRequest<Map<String, Object>> request = new BaseRequest<>();
        //sign param
        request.setMethodName(methodName);
        request.setRequestMethod(requestMethod);
        request.setMerchantNo(merchantNo);
        request.setAppId(appId);
        request.setMsgId(msgId);

        ServerHttpResponse resp = exchange.getResponse();
        if (StringUtils.isBlank(signTimestamp)) {
            logger.error("signTimestamp params is null");
            return errorService.authError(resp, GatewayExceptionEnum.SIGN_CHECK_FAIL);
        }

        request.setSignTimestamp(Long.parseLong(signTimestamp));
        long intervalTimestamp = System.currentTimeMillis() - request.getSignTimestamp();
        logger.info("request url:{},sign and request interval timestamp:{}", url, intervalTimestamp);
        if (Math.abs(intervalTimestamp) > ALLOW_INTERVAL_TIMESTAMP) {
            logger.error("intervalTimestamp {} is greater than 3min", intervalTimestamp);
            return errorService.authError(resp, GatewayExceptionEnum.SIGN_CHECK_FAIL);
        }

        request.setApiGwPublicKey(apiGwPublicKey);

        logger.info("filter sign check params:{}", JSON.toJSONString(request));
        SmileClient client = new SmileClient(request.getApiGwPublicKey(), request.getAppId(), request.getMerchantNo(), SmileConstants.SIGN_TYPE_RSA2, null, smileSecurityConfig.getPublicKey());
        try {
            //signCheck strToSign: getUserInfo?app_id=10000000006666001&charset=UTF-8&format=json&merchant_no=6666XF20230306001&method_name=getUserInfo&msg_id=666&request_method=get&sign_type=RSA2&timestamp=20230311
            client.signCheck(request, requestSign);
        } catch (RuntimeException exception) {
            return errorService.authError(resp, GatewayExceptionEnum.SIGN_CHECK_FAIL);
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -100;
    }

}

寫(xiě)博客是為了記住自己容易忘記的東西,另外也是對(duì)自己工作的總結(jié),希望盡自己的努力,做到更好,大家一起努力進(jìn)步!

如果有什么問(wèn)題,歡迎大家一起探討,代碼如有問(wèn)題,歡迎各位大神指正!

給自己的夢(mèng)想添加一雙翅膀,讓它可以在天空中自由自在的飛翔!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-641906.html

到了這里,關(guān)于Java應(yīng)用服務(wù)系統(tǒng)安全性,簽名和驗(yàn)簽淺析的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Java在物聯(lián)網(wǎng)領(lǐng)域的應(yīng)用非常廣泛,涵蓋了設(shè)備連接、數(shù)據(jù)處理、應(yīng)用程序開(kāi)發(fā)、安全性、嵌入式系統(tǒng)開(kāi)發(fā)、消息隊(duì)列和流處理、機(jī)器學(xué)習(xí)和人工智能以及跨平臺(tái)和多語(yǔ)言集成等方面

    Java在物聯(lián)網(wǎng)領(lǐng)域的應(yīng)用非常廣泛,涵蓋了設(shè)備連接、數(shù)據(jù)處理、應(yīng)用程序開(kāi)發(fā)、安全性、嵌入式系統(tǒng)開(kāi)發(fā)、消息隊(duì)列和流處理、機(jī)器學(xué)習(xí)和人工智能以及跨平臺(tái)和多語(yǔ)言集成等方面

    Java作為一種通用編程語(yǔ)言,在物聯(lián)網(wǎng)(IoT)領(lǐng)域的應(yīng)用也非常廣泛。以下是一些Java在物聯(lián)網(wǎng)中的典型應(yīng)用: 開(kāi)發(fā)物聯(lián)網(wǎng)應(yīng)用程序 :Java是一種高級(jí)編程語(yǔ)言,具有豐富的庫(kù)和工具,使得開(kāi)發(fā)物聯(lián)網(wǎng)應(yīng)用程序變得容易。Java可以用于開(kāi)發(fā)各種物聯(lián)網(wǎng)應(yīng)用程序,如智能家居、智能

    2024年02月03日
    瀏覽(95)
  • 密評(píng)|商用密碼應(yīng)用安全性評(píng)估

    作為近些年剛剛進(jìn)入人們視線(xiàn)的“密評(píng)”,許多人均對(duì)其較為陌生,密碼作為網(wǎng)絡(luò)安全體系中基礎(chǔ)支撐,是國(guó)家實(shí)現(xiàn)網(wǎng)絡(luò)安全從被動(dòng)防御走向主動(dòng)免疫的重要戰(zhàn)略轉(zhuǎn)變。 商用密碼應(yīng)用安全性評(píng)估(以下均簡(jiǎn)稱(chēng)為“密評(píng)”)于2007年提出,期間經(jīng)歷10余年的積累。 2007年11月27日,

    2024年02月13日
    瀏覽(24)
  • 區(qū)塊鏈安全性(區(qū)塊鏈應(yīng)用)

    安全性高。區(qū)塊鏈不受任何人和實(shí)體的控制,數(shù)據(jù)在多臺(tái)計(jì)算機(jī)上完整的復(fù)制。攻擊者沒(méi)有一個(gè)單一的入口點(diǎn),數(shù)據(jù)安全更有保障。數(shù)據(jù)不可篡改,一旦進(jìn)入?yún)^(qū)塊鏈,任何信息都是無(wú)法更改的,甚至管理員也無(wú)法修改此信息。無(wú)第三方并且可訪問(wèn)。區(qū)塊鏈的去中心和幫助對(duì)點(diǎn)

    2024年02月03日
    瀏覽(25)
  • URL編碼:原理、應(yīng)用與安全性

    URL編碼:原理、應(yīng)用與安全性

    在網(wǎng)絡(luò)世界中,URL(統(tǒng)一資源定位符)是我們?cè)L問(wèn)網(wǎng)頁(yè)、發(fā)送請(qǐng)求的重要方式。然而,URL 中包含的特殊字符、不安全字符以及保留字符可能會(huì)導(dǎo)致傳輸錯(cuò)誤或安全風(fēng)險(xiǎn)。為了解決這些問(wèn)題,URL 編碼應(yīng)運(yùn)而生。本文將從概念介紹、編碼規(guī)則、編碼與解碼、常見(jiàn)應(yīng)用場(chǎng)景、歷史

    2024年04月08日
    瀏覽(19)
  • 商用密碼應(yīng)用安全性測(cè)評(píng)機(jī)構(gòu)資質(zhì)流程

    商用密碼應(yīng)用安全性測(cè)評(píng)機(jī)構(gòu)資質(zhì)流程

    ? ? ? ? 商用密碼應(yīng)用安全性測(cè)評(píng)機(jī)構(gòu)(簡(jiǎn)稱(chēng)密評(píng)機(jī)構(gòu))資質(zhì)建設(shè)相關(guān)指導(dǎo)性材料包括: ? ? ? ? 1、《商用密碼應(yīng)用安全性測(cè)評(píng)機(jī)構(gòu)能力要求》 ? ? ? ? 2、《商用密碼應(yīng)用安全性測(cè)評(píng)機(jī)構(gòu)能力評(píng)審實(shí)施細(xì)則(試行)》 ? ? ? ? 3、《商用密碼應(yīng)用安全性測(cè)評(píng)機(jī)構(gòu)管理辦法(

    2024年02月08日
    瀏覽(18)
  • RIPEMD加密算法:原理、應(yīng)用與安全性

    RIPEMD加密算法:原理、應(yīng)用與安全性

    一、引言 在信息時(shí)代,數(shù)據(jù)安全愈發(fā)受到重視,加密算法作為保障信息安全的關(guān)鍵技術(shù),其性能和安全性備受關(guān)注。RIPEMD(RACE Integrity Primitives Evaluation Message Digest)加密算法作為一種著名的哈希函數(shù),廣泛應(yīng)用于網(wǎng)絡(luò)安全、數(shù)據(jù)完整性等領(lǐng)域。本文將從各個(gè)方面介紹RIPEMD加密

    2024年02月04日
    瀏覽(18)
  • 商用密碼應(yīng)用安全性評(píng)估----技術(shù)層面實(shí)現(xiàn)

    網(wǎng)絡(luò)和通信安全 ? ???? 三個(gè)密碼產(chǎn)品 ?SSL VPN IPSEC VPN? 安全認(rèn)證網(wǎng)關(guān)-----數(shù)字證書(shū)---雙證書(shū)-----SM2簽名 ?SM4加密 ??D 是否使用這些安全產(chǎn)品? ?A用的算法是否符合國(guó)家密碼算法要求?????? K密鑰管理是否安全(商用密碼產(chǎn)品檢測(cè)中心認(rèn)證的) ????? 對(duì)象:一般劃分根據(jù)

    2024年02月16日
    瀏覽(21)
  • 人臉識(shí)別技術(shù)的安全性及其應(yīng)用探討

    隨著科技的不斷發(fā)展,人臉識(shí)別技術(shù)已經(jīng)成為了一個(gè)熱門(mén)話(huà)題。人臉識(shí)別系統(tǒng)的出現(xiàn),給人們的生活帶來(lái)了極大的便利,同時(shí)也為一些犯罪分子提供了方便。因此,人臉識(shí)別技術(shù)的安全性和可靠性一直備受關(guān)注。 一、人臉識(shí)別技術(shù)的原理 人臉識(shí)別技術(shù)的原理是將人臉特征提

    2024年02月04日
    瀏覽(20)
  • 開(kāi)發(fā)日記-凌鯊中微應(yīng)用的安全性

    開(kāi)發(fā)日記-凌鯊中微應(yīng)用的安全性

    凌鯊在框架上使用了特別注重安全性的tauri框架,里面所有的權(quán)限都需要明確給出。 微應(yīng)用本質(zhì)上是靜態(tài)web頁(yè)面加上注入的額外能力。額外能力通過(guò)tauri的ipc注入和訪問(wèn)http服務(wù)。為了保證主服務(wù)的穩(wěn)定性,一些能力我們是以外掛可執(zhí)行文件的方式,通過(guò)http提供能力。 微應(yīng)用

    2024年02月12日
    瀏覽(13)
  • 商用密碼應(yīng)用與安全性評(píng)估要點(diǎn)筆記(FAQ)

    商用密碼應(yīng)用與安全性評(píng)估要點(diǎn)筆記(FAQ)

    5?商用密碼應(yīng)用安全性評(píng)估FAQ匯編 詞條 內(nèi)容 密鑰應(yīng)用基本要求的等級(jí) 一般按照信息系統(tǒng)網(wǎng)絡(luò)安全等級(jí)保護(hù)的級(jí)別確定。對(duì)于未完成網(wǎng)絡(luò)安全等級(jí)保護(hù)定級(jí)的重要信息系統(tǒng),其密碼應(yīng)用等級(jí)至少為第三級(jí)。 【宜】測(cè)評(píng)指標(biāo) 系統(tǒng)沒(méi)有密碼應(yīng)用方案或方案未對(duì)【宜】指標(biāo)明確說(shuō)

    2024年02月02日
    瀏覽(27)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包