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

網(wǎng)絡安全實驗——安全通信軟件safechat的設計

這篇具有很好參考價值的文章主要介紹了網(wǎng)絡安全實驗——安全通信軟件safechat的設計。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

網(wǎng)絡安全實驗——安全通信軟件safechat的設計

僅供參考,請勿直接抄襲,抄襲者后果自負。

倉庫地址:

后端地址:https://github.com/yijunquan-afk/safechat-server

前端地址: https://github.com/yijunquan-afk/safechat-client

CosUpload.java中的COS設置,需要自己配

1 設計要求

結合所學安全機制設計實現(xiàn)一個簡單的安全通信軟件,包含機密性,消息認證等基本功能。并考慮其中涉及的密鑰分配方式與機密性算法等相關問題的解決.實現(xiàn)方法不限,使用機制不限。

要求:

1、 獨立完成

2、 具有完整的流程設計,報文格式等相關分析。

3、 具備自圓其說的安全性設計思考

2 設計分工

3 設計原理

SHA-2

SHA-2,名稱來自于安全散列算法2(英語:Secure Hash Algorithm 2)的縮寫,一種密碼散列函數(shù)算法標準,由美國國家安全局研發(fā)[3],由美國國家標準與技術研究院(NIST)在2001年發(fā)布。屬于SHA算法之一,是SHA-1的后繼者。其下又可再分為六個不同的算法標準,包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。

RSA

RSA加密算法是一種非對稱加密算法,在公開密鑰加密和電子商業(yè)中被廣泛使用。RSA是由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)在1977年一起提出的。當時他們?nèi)硕荚诼槭±砉W院工作。RSA 就是他們?nèi)诵帐祥_頭字母拼在一起組成的。

極大整數(shù)做因數(shù)分解的難度決定了 RSA 算法的可靠性。換言之,對一極大整數(shù)做因數(shù)分解愈困難,RSA 算法愈可靠。假如有人找到一種快速因數(shù)分解的算法的話,那么用 RSA 加密的信息的可靠性就會極度下降。但找到這樣的算法的可能性是非常小的。今天只有短的 RSA 鑰匙才可能被強力方式破解。到2020年為止,世界上還沒有任何可靠的攻擊RSA算法的方式。只要其鑰匙的長度足夠長,用RSA加密的信息實際上是不能被破解的。

WebSocket協(xié)議

WebSocket是雙向的,在客戶端-服務器通信的場景中使用的全雙工協(xié)議,與HTTP不同,它以ws://或wss://開頭。它是一個有狀態(tài)協(xié)議,這意味著客戶端和服務器之間的連接將保持活動狀態(tài),直到被任何一方(客戶端或服務器)終止。在通過客戶端和服務器中的任何一方關閉連接之后,連接將從兩端終止。

以客戶端-服務器通信為例,每當啟動客戶端和服務器之間的連接時,客戶端-服務器進行握手隨后創(chuàng)建一個新的連接,該連接將保持活動狀態(tài),直到被他們中的任何一方終止。建立連接并保持活動狀態(tài)后,客戶端和服務器將使用相同的連接通道進行通信,直到連接終止。

新建的連接被稱為WebSocket。一旦通信鏈接建立和連接打開后,消息交換將以雙向模式進行,客戶端-服務器之間的連接會持續(xù)存在。如果其中任何一方(客戶端服務器)宕掉或主動關閉連接,則雙方均將關閉連接。套接字的工作方式與HTTP的工作方式略有不同,狀態(tài)代碼101表示W(wǎng)ebSocket中的交換協(xié)議。

safechat,# 計算機網(wǎng)絡安全與管理,安全,web安全,java

JWT

JWT就是通過JSON形式作為Web應用中的令牌,用于在各方之間安全地將信息作為JSON對象傳輸。在數(shù)據(jù)傳輸過程中還可以完成數(shù)據(jù)加密,簽名等相關處理。

基于JWT認證

首先,前端通過Wb表單將自己的用戶名和密碼發(fā)送到后端的接口。這一過程一般是一個HTTP POST請求。

2、后端核對用戶名和密碼成功后,將用戶的id等其他信息作為JWT Payload(負載),將其與頭部分別進行Base64編碼拼接后簽名,形成一個JWT(Token)。形成的JWT就是一個形同11.Zzz.xx的字符串。token head.payload.signature

3、后端將JWT字符串作為登錄成功的返回結果返回給前端。前端可以將返回的結果保存在localStorage或sessionStorage.上,退出登錄時前端刪除保存的JWT即可。

4、前端在每次請求時將JWT放入HTTP Header中的Authorization位。(解決XSS和XSRF問題)

5、后端檢查JWT是否存在,如存在驗證JWT的有效性。檢查簽名是否正確,檢查Token是否過期,檢查Token的接收方是否是自己(可選)

JWT結構

jwt生成的字符串包含有三部分

1、 jwt頭信息部分header:標頭通常由兩部分組成:令牌的類型(即JWT所使用的簽名算法,例如HMAC、SHA256或RSA。它會使用Base64編碼組成JWT結構的第一部分。

2、 在效載荷Payload:令牌的第二部分是有效負載,其中包含聲明。聲明是有關實體(通常是用戶)和其他數(shù)據(jù)的聲明。同樣的,它會使用Ba$64編碼組成JWT結構的第二部分

3、 簽名哈希Signature:header和payload都是結果Base64編碼過的,中間用.隔開,第三部分就是前面兩部分合起來做簽名,密鑰絕對自己保管好,簽名值同樣做Base64編碼拼接在JWT后面。(簽名并編碼)

AES

高級加密標準(英語:Advanced Encryption Standard,縮寫:AES),又稱Rijndael加密法(荷蘭語發(fā)音: [?r?inda?l],音似英文的“Rhine doll”),是美國聯(lián)邦政府采用的一種區(qū)塊加密標準。這個標準用來替代原先的DES,已經(jīng)被多方分析且廣為全世界所使用。經(jīng)過五年的甄選流程,高級加密標準由美國國家標準與技術研究院(NIST)于2001年11月26日發(fā)布于FIPS PUB 197,并在2002年5月26日成為有效的標準。現(xiàn)在,高級加密標準已然成為對稱密鑰加密中最流行的算法之一。

嚴格地說,AES和Rijndael加密法并不完全一樣(雖然在實際應用中兩者可以互換),因為Rijndael加密法可以支持更大范圍的區(qū)塊和密鑰長度:AES的區(qū)塊長度固定為128比特,密鑰長度則可以是128,192或256比特;而Rijndael使用的密鑰和區(qū)塊長度均可以是128,192或256比特。加密過程中使用的密鑰是由Rijndael密鑰生成方案產(chǎn)生。

大多數(shù)AES計算是在一個特別的有限域完成的。

AES加密過程是在一個4×4的字節(jié)矩陣上運作,這個矩陣又稱為“體(state)”,其初值就是一個明文區(qū)塊(矩陣中一個元素大小就是明文區(qū)塊中的一個Byte)。(Rijndael加密法因支持更大的區(qū)塊,其矩陣的“列數(shù)(Row number)”可視情況增加)加密時,各輪AES加密循環(huán)(除最后一輪外)均包含4個步驟:

① AddRoundKey—矩陣中的每一個字節(jié)都與該次回合密鑰(round key)做XOR運算;每個子密鑰由密鑰生成方案產(chǎn)生。

② SubBytes—透過一個非線性的替換函數(shù),用查找表的方式把每個字節(jié)替換成對應的字節(jié)。

③ ShiftRows—將矩陣中的每個橫列進行循環(huán)式移位。

④ MixColumns—為了充分混合矩陣中各個直行的操作。這個步驟使用線性轉(zhuǎn)換來混合每內(nèi)聯(lián)的四個字節(jié)。最后一個加密循環(huán)中省略MixColumns步驟,而以另一個AddRoundKey取代。

4 整體設計方案

網(wǎng)絡協(xié)議

本次設計中,我使用了HTTP協(xié)議處理一般的網(wǎng)絡請求:如登錄、注冊、好友列表獲取、個人信息獲取、頭像更新等功能。

而好友之間點對點的通信,為了持續(xù)快速地溝通,我是用WebSocket協(xié)議來處理信息發(fā)送請求。

客戶端技術選型

客戶端負責的是與用戶進行交互,因此在實用之外還需要考慮到界面美觀整潔,以給用戶帶來良好的使用體驗。因此,前端選擇使用 vue + AntDesign 組件庫進行界面構建。另一方面,由于需要建立 WebSocket 連接,發(fā)送 WebSocket 請求,因此需要引入 WebSocket 相關功能的實現(xiàn)。這里使用的是 socket.io 這一 NodeJS 第三方模塊。

safechat,# 計算機網(wǎng)絡安全與管理,安全,web安全,java

服務端技術選型

對于服務端,采用了 Java + SpringBoot 為大框架來進行服務端的開發(fā)。數(shù)據(jù)庫采用的是經(jīng)典的關系型數(shù)據(jù)庫 MySql。同時為了建立 WebSocket 連接,處理 WebSocket 請求,選擇了 socket.io 的一個 Java 移植版本 netty-socketio。netty-socketio是一個開源的Socket.io服務器端的一個java的實現(xiàn),它基于Netty框架,可用于服務端推送消息給客戶端。

safechat,# 計算機網(wǎng)絡安全與管理,安全,web安全,java

整體功能說明

本系統(tǒng)主要包含六個大的功能模塊:登陸注冊、用戶信息獲取、信息發(fā)送、好友列表顯示、頭像上傳以及退出系統(tǒng)。其中信息發(fā)送是本次課程設計最重要的部分,是安全通信的主要體現(xiàn)。

safechat,# 計算機網(wǎng)絡安全與管理,安全,web安全,java

5 安全加密部分代碼說明

整體設計

safechat,# 計算機網(wǎng)絡安全與管理,安全,web安全,java

HTTP加密

Token產(chǎn)生
private static String sign(String userId,String password){
    Algorithm algorithm = Algorithm.HMAC256(password);
    String token = JWT.create()
            .withClaim(CLAIM_USERID_NAME,userId)
            .withExpiresAt(new Date(System.currentTimeMillis()+EXPIRED_TIME/2))
            .sign(algorithm);
    return token;
}

/**
* 生成一個登錄token
* @param userId
* @param password
* @return
*/
public static String loginSign(String userId,String password){
    String token = sign(userId,password);
    cache.putToken(token,token);
    return token;
}

每次登錄產(chǎn)生Token,并存儲在前端的localStorage中,每次發(fā)送HTTP的POST和GET請求時加在HTTP Header中的Authorization位。(解決XSS和XSRF問題)

Token認證

后端接收HTTP請求時需要認證Token。

如此做可以認證發(fā)送HTTP請求的用戶身份,適用于所有HTTP請求

 /**
     * 驗證客戶端傳來token是否有效
     * 驗證邏輯順序如下:
     * 1. token是否為空
     * 2. token中賬號是否存在
     * 3. 根據(jù)token中賬號從數(shù)據(jù)庫中獲取真實密碼等用戶信息,并驗證用戶信息是否有效
     */
    public static void verifyToken(String clientToken, stu.software.chatroom.common.CommonService commonService){
        if(!StringUtils.hasText(clientToken)){
            //token為空
            throw new RuntimeException("無登錄令牌!");
        }

        //從客戶端登錄令牌中獲取當前用戶賬號
        String userId = JWT.decode(clientToken).getClaim(CLAIM_USERID_NAME).asString();
        if(!StringUtils.hasText(userId)){
            //token中賬號不存在
            throw new RuntimeException("登錄令牌失效!");
        }

        //取出緩存中的登錄令牌
        String cacheToken = cache.getToken(clientToken);
        if(!StringUtils.hasText(cacheToken)){
            //緩存中沒有登錄令牌
            throw new RuntimeException("登錄令牌失效!");
        }

        User user = commonService.getUserById(userId);
        if(user==null){
            //用戶不存在
            throw new RuntimeException("用戶不存在!");
        }

        //驗證Token有效性
        try{
            Algorithm algorithm = Algorithm.HMAC256(user.getU_pwd());
            JWTVerifier jwtVerifier = JWT.require(algorithm).withClaim(CLAIM_USERID_NAME,userId).build();//構建驗證器
            jwtVerifier.verify(cacheToken);
        }catch(TokenExpiredException e){
            //令牌過期,刷新令牌
            String newToken = sign(userId,user.getU_pwd());
            cache.putToken(clientToken,newToken);
        }catch(Exception e){
            e.printStackTrace();
            //令牌驗證未通過
            throw new RuntimeException("令牌錯誤!請登錄。");
        }

注冊密碼加密

使用SHA256加密注冊時用戶使用的密碼,數(shù)據(jù)庫中存的是密文,這樣可防止數(shù)據(jù)庫被攻擊導致密碼泄露。

/***
* 利用Apache的工具類實現(xiàn)SHA-256加密
* @return str 加密后的報文
*/
public static String getSHA256Str(String str) {
    MessageDigest messageDigest;
    String encodeSir = str;
    try {
        messageDigest = MessageDigest.getInstance("SHA-256");
        byte[] hash = messageDigest.digest(str.getBytes(StandardCharsets.UTF_8));
        encodeSir = Hex.encodeHexString(hash);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return encodeSir;
}

/**
* 通過該方法將密碼加密(實際上并沒有)
*/
public static String encodePwd(String u_pwd) {
    // 密碼通過此方法解密并再加密
    return getSHA256Str(u_pwd);
}

登錄密碼加密

登錄時,前端輸入明文密碼,使用SHA256加密該密碼以后,再加數(shù)據(jù)發(fā)送到后端。后端根據(jù)該加密后的密碼與數(shù)據(jù)庫比對,從而驗證用戶身份。

此做法避免了前端請求數(shù)據(jù)被攔截導致密碼泄露。

import { sha256 } from 'js-sha256';

/**
 * 加密方法
 */
export function PASSWORD(str) {
    let encodedStr = str;
    encodedStr = sha256(encodedStr);
    return encodedStr;
}
const login = () => {
  post("/user/login", {
    u_name: u_name.value,
    u_pwd: PASSWORD(u_pwd.value),
  })
    .then((res) => {
      tip.success(res.message);
      let token = res.data;
      setLocalToken(token);
      router.push({ name: "Room", query: { usr: u_name.value } });
    })
    .catch((err) => {
      tip.error("賬號密碼錯誤!");
    });
};

密鑰分配——使用Keytool

參考教程 https://blog.csdn.net/m0_59579040/article/details/124811147

keytool 是個密鑰和證書管理工具。它使用戶能夠管理自己的公鑰/私鑰對及相關證書,用于(通過數(shù)字簽名)自我認證(用戶向別的用戶/服務認證自己)或數(shù)據(jù)完整性以及認證服務。它還允許用戶儲存他們的通信對等者的公鑰(以證書形式)。

在計算機網(wǎng)絡上,OpenSSL是一個開放源代碼的軟件庫包,應用程序可以使用這個包來進行安全通信,避免竊聽,同時確認另一端連接者的身份。這個包廣泛被應用在互聯(lián)網(wǎng)的網(wǎng)頁服務器上。

通過如下步驟可以產(chǎn)生證書和公鑰

keytool -genkeypair -storetype PKCS12 -alias yjq - -keyalg RSA -keysize 1024 -dname "CN=xxx, OU=xxx, O=xxx, L=xx, ST=xx, C=CN" -keystore D:\mygit\大三下筆記\網(wǎng)安課設\safechat-server\src\main\resources\keys-and-certs\yjq.keystore -keypass 123456 -storepass 123456 -validity 36500 -v  

產(chǎn)生二進制文件yjq.keystore,以上部分可由腳本生成。

經(jīng)過KeyStore的相關操作生成公鑰、證書和私鑰

safechat,# 計算機網(wǎng)絡安全與管理,安全,web安全,java

當用戶需要公鑰和私鑰時,只需要調(diào)用相關方法即可。

public static void genKeyPair(String name) throws Exception {  
    //以 PKCS12 規(guī)格,創(chuàng)建 KeyStore  
    KeyStore keyStore = KeyStore.getInstance("PKCS12");  
    path = "keys-and-certs/" + name + ".keystore";  
    //載入 jks 和該 jks 的密碼 到 KeyStore 內(nèi)  
    keyStore.load(new FileInputStream(new ClassPathResource("keys-and-certs/yjq.keystore").getFile()), "123456".toCharArray());  
  
    // 要獲取 key,需要提供 KeyStore 的別名 和該 KeyStore 的密碼  
    // 獲取 keyStore 內(nèi)所有別名 alias  
    Enumeration<String> aliases = keyStore.aliases();  
    String alias = null;  
    alias = aliases.nextElement();  
    char[] keyPassword = "123456".toCharArray();  
    keyPairString.clear();  
    //私鑰  
    privateKey = (PrivateKey) keyStore.getKey(alias, keyPassword);  
    keyPairString.put("PR", new String(Base64.getEncoder().encode(privateKey.getEncoded())));  
    //證書  
    Certificate certificate = keyStore.getCertificate(alias);  
    //公鑰  
    publicKey = certificate.getPublicKey();  
    keyPairString.put("PU", new String(Base64.getEncoder().encode(publicKey.getEncoded())));  
  
} 

使用公鑰加密保證消息認證和機密性

參考教程https://blog.csdn.net/m0_59579040/article/details/124811147.

A和B進行通信,首先使用A的私鑰對報文M進行加密——數(shù)字簽名;然后A用B的公鑰對上述結果進行加密——保證了保密性。

B收到消息后,用B的私鑰解密,再用A的公鑰驗證簽名。

safechat,# 計算機網(wǎng)絡安全與管理,安全,web安全,java

這里我使用RSA作為加密算法、SHA1WithRSA作為簽名算法,簽名和加密的操作實現(xiàn)在類RSAUtils.java中。

簽名
/** 
* 私鑰簽名 
* @param content 字符串 
* @param priKey 私鑰 
* @return 
* @throws Exception 
*/  
public static byte[] sign(String content, PrivateKey priKey) throws Exception {  
    Signature signature = Signature.getInstance(SIGALG);  
    signature.initSign(priKey);  
    signature.update(content.getBytes());  
    return signature.sign();  
}  
  
/** 
* 公鑰驗證簽名 
* @param content 字符串 
* @param sign 簽名 
* @param pubKey 公鑰 
* @return 身份是否真實 
* @throws Exception 
*/  
public static boolean verify(String content, byte[] sign, PublicKey pubKey) throws Exception {  
  
    Signature signature = Signature.getInstance(SIGALG);  
    signature.initVerify(pubKey);  
    signature.update(content.getBytes());  
    return signature.verify(sign);  
}  

加密解密
/** 
* RSA公鑰加密 
* 
* @param content       加密字符串 
* @param publicKey 公鑰 
* @return 密文 
* @throws Exception 加密過程中的異常信息 
*/  
public static String encrypt(String content, String publicKey) throws Exception {  
    //base64編碼的公鑰  
    byte[] decoded = Base64.getMimeDecoder().decode(publicKey);  
    RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance(KEYALG).generatePublic(new X509EncodedKeySpec(decoded));  
    System.out.println(pubKey.getAlgorithm());  
    //RSA加密  
    Cipher cipher = Cipher.getInstance(KEYALG);  
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);  
    String outStr = Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes("UTF-8")));  
    return outStr;  
}  
  
/** 
* RSA私鑰解密 
* 
* @param content        加密字符串 
* @param privateKey 私鑰 
* @return 明文 
* @throws Exception 解密過程中的異常信息 
*/  
public static String decrypt(String content, String privateKey) throws Exception {  
  
    //64位解碼加密后的字符串  
    byte[] inputByte = Base64.getMimeDecoder().decode(content);  
    //        //base64編碼的私鑰  
    byte[] decoded = Base64.getMimeDecoder().decode(privateKey);  
    RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));  
    //RSA解密  
    Cipher cipher = Cipher.getInstance("RSA");  
    cipher.init(Cipher.DECRYPT_MODE, priKey);  
    String outStr = new String(cipher.doFinal(inputByte));  
    return outStr;  
}  

使用AES加密消息

因為公鑰加密的消息認證比較費時間,所以當兩個用戶建立消息通信時由一方產(chǎn)生會話密鑰,使用公鑰加密來傳送會話密鑰并認證身份。身份認證完成后,使用該會話密鑰加密消息,其中使用對稱加密技術AES加密消息。

消息報文格式如下:

1、 id:報文標識id;

2、 time:報文發(fā)送時間

3、 content:報文內(nèi)容(加密)

4、 type:報文類型:會話密鑰消息/公鑰消息

5、 sender_name:發(fā)送者

6、 receiver_name:接收者

7、 sign:發(fā)送者簽名。

加密過程如下:

public final class AESUtils{  
    private static final String ALGORITHM = "AES";  
    public static String genAesSecret(){  
        try {  
            KeyGenerator kg = KeyGenerator.getInstance("AES");  
            //下面調(diào)用方法的參數(shù)決定了生成密鑰的長度,可以修改為128, 192或256  
            kg.init(256);  
            SecretKey sk = kg.generateKey();  
            byte[] b = sk.getEncoded();  
            String secret = Base64.encodeBase64String(b);  
            return secret;  
        }  
        catch (NoSuchAlgorithmException e) {  
            e.printStackTrace();  
            throw new RuntimeException("沒有此算法");  
        }  
    }  
    /** 
     * 根據(jù)密鑰對指定的明文plainText進行加密. 
     * 
     * @param plainBytes 明文 
     * @param keyBytes   密碼 
     * @return 加密后的密文. 
     * @since 0.0.8 
     */  
    public static byte[] encrypt(byte[] plainBytes, byte[] keyBytes) {  
        try {  
            SecretKey secretKey = getSecretKey(keyBytes);  
            Cipher cipher = Cipher.getInstance(ALGORITHM);  
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);  
            return cipher.doFinal(plainBytes);  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  
    }  
  
    /** 
     * 根據(jù)密鑰對指定的密文 cipherBytes 進行解密. 
     * 
     * @param cipherBytes 加密密文 
     * @param keyBytes    秘鑰 
     * @return 解密后的明文. 
     * @since 0.0.8 
     */  
    public static byte[] decrypt(byte[] cipherBytes, byte[] keyBytes) {  
        try {  
            SecretKey secretKey = getSecretKey(keyBytes);  
  
            Cipher cipher = Cipher.getInstance(ALGORITHM);  
            cipher.init(Cipher.DECRYPT_MODE, secretKey);  
            return cipher.doFinal(cipherBytes);  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  
    }  
  
    /** 
     * 獲取加密 key 
     * @param keySeed seed 
     * @return 結果 
     * @since 0.0.8 
     */  
    private static SecretKey getSecretKey(byte[] keySeed) {  
        try {  
            // 避免 linux 系統(tǒng)出現(xiàn)隨機的問題  
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); 
            secureRandom.setSeed(keySeed);  
            KeyGenerator generator = KeyGenerator.getInstance("AES");  
            generator.init(secureRandom);  
            return generator.generateKey();  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  
    }  
}  

服務端加密

結合RSA與AES的加密如下:

先用公鑰加密RSA發(fā)送對稱加密使用的會話密鑰,然后再用會話密鑰進行AES對稱加密通信。

 // 監(jiān)聽客戶端發(fā)送消息  
socketIOServer.addEventListener(Constants.EVENT_MESSAGE_TO_SERVER, String.class, (client, data, ackSender) -> {  
    String sender_name = getParamsByClient(client, "u_name");  
    ObjectMapper mapper = new ObjectMapper();  
    Message message = mapper.readValue(data, Message.class);  
    String receiver_name = message.getReceiver_name();  
  
    if (message.getType().equals(Constants.MASTER_MESSAGE)) {  
        //使用公鑰加密傳送會話密鑰  
        if (AesKey.equals("")) {  
            log.info("用戶" + sender_name + "生成會話密鑰");  
            AesKey = AESUtils.genAesSecret();  
            message.setContent(AesKey);  
            log.info("用戶" + sender_name + "使用用戶" + sender_name + "的私鑰對會話密鑰進行簽名");  
            String sign = new String(RSAUtils.sign(message.getContent(), RSAUtils.getPrivateKey()), "ISO-8859-1");  
            message.setSign(sign);  
            String result = RSAUtils.encrypt(message.getContent(), publicKeyStringMap.get(receiver_name));  
            log.info("使用用戶" + receiver_name + "的公鑰對會話密鑰進行加密:" + result);  
            message.setContent(result);  
            sendMessageToFriend(message.getReceiver_name(), message);  
        } else {  
            return;  
        }  
    } else {  
        //使用會話密鑰發(fā)送消息  
        byte[] bytes = AESUtils.encrypt(message.getContent().getBytes(), AesKey.getBytes());  
        String encrypt = new String(bytes, "ISO-8859-1");  
        log.info("用戶" + sender_name + "使用會話密鑰加密消息");  
        message.setContent(encrypt);  
        sendMessageToFriend(message.getReceiver_name(), message);  
    }    
});  
//  
//GBK,  GB2312,UTF-8等一些編碼方式為多字節(jié)或者可變長編碼,原來的字節(jié)數(shù)組就被改變了,再轉(zhuǎn)回原來的byte[]數(shù)組就會發(fā)生錯誤了。  
//ISO-8859-1通常叫做Latin-1,Latin-1包括了書寫所有西方歐洲語言不可缺少的附加字符,其中 0~127的字符與ASCII碼相同,  
// 它是單字節(jié)的編碼方式,在來回切換時不會出現(xiàn)錯誤。  
  
// 監(jiān)聽客戶端接收消息  
socketIOServer.addEventListener("receive_triger", String.class, (client, data, ackSender) -> {   
    ObjectMapper mapper = new ObjectMapper();  
    Message message = mapper.readValue(data, Message.class);  
    String sender_name = message.getSender_name();  
    String receiver_name = message.getReceiver_name();  
    if (message.getType().equals(Constants.MASTER_MESSAGE)) {  
        log.info("收到來自" + sender_name + "發(fā)送給" + message.getReceiver_name() + "的消息: " + message.getContent());  
        String result = RSAUtils.decrypt(message.getContent(), RSAUtils.getKeyPair().get("PR"));  
        log.info("用戶" + receiver_name + "使用用戶" + receiver_name + "的私鑰對消息進行解密:");  
        message.setContent(result);  
        log.info("用戶" + receiver_name + "使用用戶" + sender_name + "的公鑰對消息進行驗證簽名");  
        Boolean sign = (RSAUtils.verify(message.getContent(), message.getSign().getBytes("ISO-8859-1"), publicKeyMap.get(sender_name)));  
        if (sign) {  
            log.info("簽名驗證成功!身份無誤");  
        } else {  
            throw new Exception("簽名錯誤!");  
        }  
        receiveMessageFromFriend(message.getReceiver_name(), message);  
    } else {  
        log.info("收到來自" + sender_name + "發(fā)送給" + message.getReceiver_name() + "的消息: " + message.getContent());  
        String text = new String(AESUtils.decrypt(message.getContent().getBytes("ISO-8859-1"), AesKey.getBytes()), "UTF-8");  
        log.info("用戶" + receiver_name + "使用會話密鑰進行解密");  
        message.setContent(text);  
        receiveMessageFromFriend(message.getReceiver_name(), message);  
    }  
});

6 演示

登錄

safechat,# 計算機網(wǎng)絡安全與管理,安全,web安全,java

進入主頁面

可以看到好友列表

safechat,# 計算機網(wǎng)絡安全與管理,安全,web安全,java

同時獲取本地密鑰庫中的公私鑰并將其加入公鑰庫

safechat,# 計算機網(wǎng)絡安全與管理,安全,web安全,java

選擇好友進行私聊

選擇好友進行私聊,進入聊天界面。

safechat,# 計算機網(wǎng)絡安全與管理,安全,web安全,java

safechat,# 計算機網(wǎng)絡安全與管理,安全,web安全,java

發(fā)送消息

在輸入框中輸入消息,點擊發(fā)送,接收者和發(fā)送者的聊天框都會出現(xiàn)相應的消息。此消息是經(jīng)過后端AES對稱加密解密得到的。

safechat,# 計算機網(wǎng)絡安全與管理,安全,web安全,java文章來源地址http://www.zghlxwxcb.cn/news/detail-816760.html

到了這里,關于網(wǎng)絡安全實驗——安全通信軟件safechat的設計的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

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

領支付寶紅包贊助服務器費用

相關文章

  • SSCOM串口軟件模擬TCP通信接發(fā)信息

    SSCOM串口軟件模擬TCP通信接發(fā)信息

    開兩個頁面,一個做服務端Server,一個做客戶端Client 注意紅框保持一致,服務端點偵聽,客戶端點鏈接,即可通信。

    2024年02月12日
    瀏覽(16)
  • 通信算法之130:軟件無線電-接收機架構

    通信算法之130:軟件無線電-接收機架構

    ? 1. 超外差式接收機 ? ?2.零中頻接收機 ?3.數(shù)字中頻接收機 ? ?

    2023年04月10日
    瀏覽(31)
  • STM32單片機初學4-IIC通信(軟件模擬)

    STM32單片機初學4-IIC通信(軟件模擬)

    IIC ( Inter-Integrated Circuit )又稱I2C(習慣讀“I方C”),是 IIC Bus簡稱,中文名為 集成電路總線 ,它是一種串行通信總線,使用多主從架構,由飛利浦公司在1980年代為了讓主板、嵌入式系統(tǒng)或手機用以連接低速周邊設備而發(fā)展。適用于IC間的短距離數(shù)據(jù)傳輸。 最初的IIC通信速

    2024年02月05日
    瀏覽(102)
  • 力控軟件與S7-200SMART無線PPI通信

    力控軟件與S7-200SMART無線PPI通信

    在實際系統(tǒng)中,人機界面與PLC通常不在一起,中心計算機一般放置在控制室,而PLC安裝在現(xiàn)場車間,二者之間距離往往從幾十米到幾千米。如果布線的話,需要挖溝施工,比較麻煩,這種情況下比較適合采用無線通信方式。因為采用無線PPI協(xié)議響應速度快且不需要編程,只需

    2024年02月10日
    瀏覽(21)
  • STM32軟件模擬IIC時序?qū)崿F(xiàn)與EEPROM的通信

    STM32軟件模擬IIC時序?qū)崿F(xiàn)與EEPROM的通信

    ???????????????????IIC簡介 ?IIC物理層 用軟件模擬IIC時序 ????????一、空閑狀態(tài)(初始化):SCL 和SDA都保持高電平 ????????二、開始信號 :SCL為高電平期間,SDA由高電平變?yōu)榈碗娖健?????????三、停止信號:SCL為高電平期間,SDA由低電平變?yōu)楦唠娖???

    2024年02月09日
    瀏覽(21)
  • 【AUTOSAR】軟件架構中的接口設計與跨核通信解析

    目錄 前言 一、什么是接口? 二、什么是CS接口?什么是SR接口?區(qū)別是什么?

    2024年02月03日
    瀏覽(17)
  • 網(wǎng)絡安全實驗——web安全

    網(wǎng)絡安全實驗——web安全

    目錄 實驗目的 實驗原理 實驗內(nèi)容 實驗1 1. 地址欄中執(zhí)行腳本 2. 對DOM技術的利用 實驗2? 1.jump1 2.jump2 3.get 4.xss 5.注冊bss 6.盜取cookie 7.分析cookie ?實驗3 一.搭建IIS服務器 二.身份驗證和權限設置 三.IP地址和域名限制 四.安全通信 五. 單點登錄 ?實驗總結 1. 了解什么是XSS 2. 掌握盜

    2024年02月13日
    瀏覽(30)
  • [Ubuntu 20.04 PC] 安裝C-Kermit:一個開源串口通信軟件

    在計算機科學領域,串口通信一直是非常重要的一環(huán)。而C-Kermit作為一款強大而靈活的開源串口通信軟件,廣泛應用于UNIX、Linux和Windows等操作系統(tǒng)中。本文將介紹C-Kermit的基本原理、特點以及如何使用它進行串口通信。 C-Kermit是由C語言實現(xiàn)的,旨在提供可靠、高效的串口通信

    2024年02月11日
    瀏覽(16)
  • Modbus通信協(xié)議介紹以及Modbus Poll、Slave軟件使用介紹

    Modbus通信協(xié)議介紹以及Modbus Poll、Slave軟件使用介紹

    Modbus Slave是一個模擬Modbus協(xié)議從機的上位機軟件,主要用于模擬測試跟其他主機設備通信的過程。與之成套存在的另一個軟件--Modbus Poll,則是模擬Modbus協(xié)議主機的上位機軟件。該軟件內(nèi)部封裝Modbus協(xié)議,通過圖形化界面使得操作更為簡單。軟件支持ModbusRTU、ASCII、TCP/IP協(xié)議。

    2024年02月09日
    瀏覽(29)
  • 手機電腦scoket通信 手機軟件 APP inventor 服務端程序python

    手機電腦scoket通信 手機軟件 APP inventor 服務端程序python

    再幫助同學坐課題的時候接觸到了scoket通信,了解到這應該是基層網(wǎng)絡通信的原理,于是就導出搜索了一下相關的資料,簡單來說scoket通信就是,可以讓不同設備在同一個網(wǎng)絡環(huán)境的條件下,可以實現(xiàn)相互通信既可以一對一也可以一對多,總之這對開發(fā)者來說,是跨設備交互

    2024年02月10日
    瀏覽(17)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領取紅包

二維碼2

領紅包