API安全性:使用散列来维护客户端和服务器之间的数据完整性

时间:2019-01-10 08:52:21

标签: android api spring-boot

我有一个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(为简便起见,删除了Setter和getter)

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 "";
    }
}

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:0)

您可以将HashString方法放入SignUpUserRequest中,并在两端使用它。 如前所述,作为攻击的一部分,攻击者可以自己更改哈希,从而使您无法通过检查-这是否是问题,取决于您要缓解的威胁。如果您想适当保护邮件,请看一下DSA(数字安全算法)。

对于大多数实施方式,您可以只通过https发送注册,并依靠SSL连接来确保完整性。