API安全性:使用散列来维护客户端和服务器之间的数据完整性 [英] API Security : Using Hashing to Maintain data Integrity Between Client and Server

查看:43
本文介绍了API安全性:使用散列来维护客户端和服务器之间的数据完整性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Android客户端,可将JSON数据发送到我的spring boot应用程序服务器.

为了在通信过程中保持一定级别的数据完整性,我要求对原始有效负载进行哈希处理,然后将其与原始JSON数据一起设置为传出有效负载.

这是我的意思(Android客户端)

signUpUserRequest = new SignUpUserRequest(
                        lastName.getText().toString(),
                        Long.valueOf(phoneNumber.getText().toString().trim()),
                        emailAddress.getText().toString(),
                        Config.getAndroidId(this),
                        Type.INDIVIDUAL.toString(),
                        firstName.getText().toString(),
                        Config.ToBase64Encode(confirmPassword.getText().toString())
                );
                signUpUserRequest.setHash(Config.HashString(signUpUserRequest.toDataString().trim()));

下面是SignUpUserRequest Pojo(为简便起见,删除了设置员和获取者)

public class SignUpUserRequest {

private String firstName;

private String lastName;

private long phoneNumber;

private String type;

private String email;

private String password;

private String phoneId;

private String hash;

public SignUpUserRequest(String lastName, Long phoneNumber, String email, String phoneId, String type, String firstName, String password) {
    this.lastName = lastName;
    this.phoneNumber = phoneNumber;
    this.email = email;
    this.phoneId = phoneId;
    this.type = type;
    this.firstName = firstName;
    this.password = password;
}
.... setters and getters removed ....

public String toDataString() {
    return "SignUpUserRequest{" + "firstName=" + firstName + ", lastName=" + lastName + ", phoneNumber=" + phoneNumber + ", type=" + type + ", email=" + email + ", password=" + password + ", phoneId=" + phoneId + '}';
}

@Override
public String toString() {
    return "SignUpUserRequest{" + "firstName=" + firstName + ", lastName=" + lastName + ", phoneNumber=" + phoneNumber + ", type=" + type + ", email=" + email + ", password=" + password + ", phoneId=" + phoneId + ", hash=" + hash + '}';
}

我遇到的问题是,当我将JSON发送到spring boot应用程序,然后对请求数据进行完整性检查时,服务器端生成的哈希值始终与客户端端生成的哈希值不同.

服务器端代码(Spring启动应用程序)

 public ResponseEntity getSignupSessionJWTToken(@RequestBody SignUpUserRequest request) {
    Response response = new Response();
    String hashString = Config.HashString(request.toDataString().trim());

   if (hashString.equals(request.getHash())) {
   ...... do anything here .....
   }else{
   ..... integrity exception ....
   }

所以我的问题是正确的方法吗? 我是从根本上做错了什么,如何最好地实现客户端和服务器之间的数据完整性.

hashString(Android)的实现

public static String HashString(String text) {
    try {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(text.trim().getBytes("UTF-8"));
        Log.i("CONFIG", "HASHING TEXT = " + ToBase64Encode(hash));
        return ToBase64Encode(hash);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(Config.class.getName()).log(Level.SEVERE, null, ex);
        return "";
    } catch (UnsupportedEncodingException e) {
        Logger.getLogger(Config.class.getName()).log(Level.SEVERE, null, e);
        return "";
    }
}

public static String ToBase64Encode(byte[] originalInput) {
    return new String(Base64.encodeToString(originalInput, Base64.DEFAULT));
}

hashString(SpringBoot)的实现

public static String HashString(String text) {
    try {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
        // System.out.println("Compare this = " + ToBase64Encode(hash));
        return Base64.getEncoder().encodeToString(hash);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(RiceHelper.class.getName()).log(Level.SEVERE, null, ex);
        return "";
    }
}

解决方案

客户端的base64输出不安全,因为它在编码时使用Base64.DEFAULT标志.当在服务器端接收到编码结果时,"+"字符将转换为-"字符.因此,比较失败.为了验证这一点,您可以从客户端发送的编码base64字符串以及从服务器端接收的字符串.

要使其网址安全,请使用-

byte[] encoded = Base64.encode(
strBytes, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);

I have an Android client that sends JSON data to my spring boot application server.

In other to maintain a certain level of data integrity during communication I require that the original payload be hashed and then set into the outgoing payload along with the original JSON data.

This is what I mean (Android Client)

signUpUserRequest = new SignUpUserRequest(
                        lastName.getText().toString(),
                        Long.valueOf(phoneNumber.getText().toString().trim()),
                        emailAddress.getText().toString(),
                        Config.getAndroidId(this),
                        Type.INDIVIDUAL.toString(),
                        firstName.getText().toString(),
                        Config.ToBase64Encode(confirmPassword.getText().toString())
                );
                signUpUserRequest.setHash(Config.HashString(signUpUserRequest.toDataString().trim()));

Below is the the SignUpUserRequest Pojo (Setters and getters removed for brevity)

public class SignUpUserRequest {

private String firstName;

private String lastName;

private long phoneNumber;

private String type;

private String email;

private String password;

private String phoneId;

private String hash;

public SignUpUserRequest(String lastName, Long phoneNumber, String email, String phoneId, String type, String firstName, String password) {
    this.lastName = lastName;
    this.phoneNumber = phoneNumber;
    this.email = email;
    this.phoneId = phoneId;
    this.type = type;
    this.firstName = firstName;
    this.password = password;
}
.... setters and getters removed ....

public String toDataString() {
    return "SignUpUserRequest{" + "firstName=" + firstName + ", lastName=" + lastName + ", phoneNumber=" + phoneNumber + ", type=" + type + ", email=" + email + ", password=" + password + ", phoneId=" + phoneId + '}';
}

@Override
public String toString() {
    return "SignUpUserRequest{" + "firstName=" + firstName + ", lastName=" + lastName + ", phoneNumber=" + phoneNumber + ", type=" + type + ", email=" + email + ", password=" + password + ", phoneId=" + phoneId + ", hash=" + hash + '}';
}

The problem I have is when I send the JSON over to my spring boot application and then carry out an integrity check on the request data, the hash generated on the server side is always different from the hash generated on the client side.

Server Side Code (Spring boot Application)

 public ResponseEntity getSignupSessionJWTToken(@RequestBody SignUpUserRequest request) {
    Response response = new Response();
    String hashString = Config.HashString(request.toDataString().trim());

   if (hashString.equals(request.getHash())) {
   ...... do anything here .....
   }else{
   ..... integrity exception ....
   }

So My question is this the right approach? Am I doing something fundamentally wrong and how best can I achieve data integrity between my client and server.

Implementation of the hashString (Android)

public static String HashString(String text) {
    try {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(text.trim().getBytes("UTF-8"));
        Log.i("CONFIG", "HASHING TEXT = " + ToBase64Encode(hash));
        return ToBase64Encode(hash);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(Config.class.getName()).log(Level.SEVERE, null, ex);
        return "";
    } catch (UnsupportedEncodingException e) {
        Logger.getLogger(Config.class.getName()).log(Level.SEVERE, null, e);
        return "";
    }
}

public static String ToBase64Encode(byte[] originalInput) {
    return new String(Base64.encodeToString(originalInput, Base64.DEFAULT));
}

Implementation of the hashString (SpringBoot)

public static String HashString(String text) {
    try {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
        // System.out.println("Compare this = " + ToBase64Encode(hash));
        return Base64.getEncoder().encodeToString(hash);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(RiceHelper.class.getName()).log(Level.SEVERE, null, ex);
        return "";
    }
}

解决方案

The base64 output at your client side is not Url safe since it uses Base64.DEFAULT flag while encoding. The "+" character in the encoded result is being converted to a "-" character when received at the server side. Hence the comparison is failing. To verify this you can the encoded base64 string you are sending from your client and the string you receive at the server side.

To make it Url safe, use -

byte[] encoded = Base64.encode(
strBytes, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);

这篇关于API安全性:使用散列来维护客户端和服务器之间的数据完整性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆