具有质询-响应的认证系统

Posted

技术标签:

【中文标题】具有质询-响应的认证系统【英文标题】:Authentication System with Challenge-Response 【发布时间】:2022-01-21 13:24:43 【问题描述】:

我对 Java 很陌生,对编程也很陌生。我的任务是建立一个至少有两个用户和一个挑战-响应-请求的身份验证系统。 我使用 MD5 和 Salt 生成了密码哈希,我只是找不到一种方法来询问客户端输入的密码是否等于生成的密码哈希。我也不知道如何告诉我的客户盐是什么。

这是我目前构建的。

Server
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class server 

    ServerSocket serversocket;
    Socket client;

    BufferedReader input;
    PrintWriter output;

    public void start() throws IOException
        serversocket = new ServerSocket(9090);
        System.out.println("Connection Starting on port:" + serversocket.getLocalPort() );
        //make connection to client on port specified


        //accept connection from client
        client = serversocket.accept();

        System.out.println("Waiting for connection from client");

        try 
            logInfo();
         catch (Exception e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
    
    

    public static void main1(String[] args) throws Exception 
        
        String pass1 = "karotte";
        String pass2 = "tomate";
        
        String algorithm = "MD5";
        byte[] salt = createSalt();
        System.out.println("Bob MD5 Hash: "+ generateHash1(pass1, algorithm, salt));
        System.out.println("Alice MD5 Hash: "+ generateHash2(pass2, algorithm, salt));
        
    

    private static 
    String generateHash1(String pass1, String algorithm, byte[] salt) throws NoSuchAlgorithmException 
        MessageDigest digest = MessageDigest.getInstance(algorithm);
        digest.reset();
        digest.update(salt);
        byte[] hash = digest.digest(pass1.getBytes());
        return bytesToStringHex(hash);
    


    static String generateHash2(String pass2, String algorithm, byte[] salt) throws NoSuchAlgorithmException 
        MessageDigest digest = MessageDigest.getInstance(algorithm);
        digest.reset();
        digest.update(salt);
        byte[] hash = digest.digest(pass2.getBytes());
        return bytesToStringHex(hash);
        
    

    private final static char[] hexArray = "0123456789ABCDEF".toCharArray();

    public static String bytesToStringHex(byte[] bytes) 
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) 
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        
        return new String(hexChars);
    

    public static byte[] createSalt() 
    byte[] bytes = new byte[5];
    SecureRandom random = new SecureRandom();
    random.nextBytes(bytes);
    return bytes;
    

    public void logInfo() throws Exception
        //open buffered reader for reading data from client

        input = new BufferedReader(new InputStreamReader(client.getInputStream()));

        
        
        String username = input.readLine();
        System.out.println("username" + username);
        String password = input.readLine();
        System.out.println("password" + password);

        //open printwriter for writing data to client
        output = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));


        if(username.equals("Bob") &&password.equals())
            output.println("Welcome, " + username);
        else 
        if
         (username.equals("Alice) &&password.equals())
            output.println("Welcome, "+ username);
        else
            output.println("Login Failed");
        
        output.flush();
        output.close();

    
    public static void main(String[] args)
        server server = new server();
        try 
            server.start();
         catch (IOException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
           

 

Client
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JOptionPane;


public class client 


    Socket socket;
    BufferedReader read;
    PrintWriter output;

    public void startClient() throws UnknownHostException, IOException
        //Create socket connection
        socket = new Socket("localhost", 9090);

        //create printwriter for sending login to server
        output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));

        //prompt for user name
        String username = JOptionPane.showInputDialog(null, "Enter User Name:");

        //send user name to server
        output.println(username);

        //prompt for password
        String password = JOptionPane.showInputDialog(null, "Enter Password");

        //send password to server
        output.println(password);
        output.flush();

        //create Buffered reader for reading response from server
        read = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        //read response from server
        String response = read.readLine();
        System.out.println("This is the response: " + response);

        //display response
        JOptionPane.showMessageDialog(null, response);
    



    public static void main(String args[])
        client client = new client();
        try 
            client.startClient();
         catch (UnknownHostException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
         catch (IOException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
    
 ```

【问题讨论】:

为什么客户需要知道盐是什么? 因为响应是 Hash = (challenge + password)。那么盐不是挑战吗? 【参考方案1】:

如果您是关于客户端/服务器连接,为什么不使用基于 SSl 和 X509 证书的相互身份验证? 它易于设置并增加了额外的安全性。

【讨论】:

以上是关于具有质询-响应的认证系统的主要内容,如果未能解决你的问题,请参考以下文章

HTTP基本认证

基本认证机制

基本认证机制

为啥质询-响应方法是忘记密码的糟糕解决方案?

使用 WebAuthenticationConfiguration 时启用 401 质询响应

带有证书管理器和 Nginx 入口的 404 质询响应