繁体   English   中英

应用程序上的 Java 解密,反编译的源代码

[英]Java decryption on an app, decompiled source code

检查这段代码几个小时后,对发生了什么有一点点了解,但我来自 python,这完全不同。

我只是查找了 StringBuilder 之类的基本内容,并且可以将其理解为简单。 对于某些人来说,这可能是一个简单的散列算法,但这是我第一次尝试像public final String getSignature(String paramString1, String paramString2) ,这是我部分理解的方法/函数。 它获取电子邮件和时间戳,并将它们添加到带有 : 的字符串构建器中。

然而,这(至少我认为)不可能是创建请求中使用的签名所需的唯一函数,所以这让我想到了下一个问题,所有其他函数在做什么,比如为什么在第一个函数中这样做将""附加到StringBuilder ,这对我来说似乎毫无意义,而第一个函数中的 ParamString 是什么。

我的总体问题是这是如何工作的? 我已经看了这段代码至少 2 个小时,但我觉得没有任何进展。 Charset charset = Charsets.UTF_8; 绝对是不言自明的,但是诸如Intrinsics.checkExpressionValueIsNotNull(arrayOfByte2, "(this as java.lang.String).getBytes(charset)"); 不是,而且很难理解。

这是文件Signature.class中的所有代码,所以我确定这是所有代码。 我不是要求对所有事情进行细分。 我最困惑的是如何在方法/函数上使用参数。 例如,我如何判断public Signature(String paramString) String paramString 是什么。 我知道我在整个过程中问了很多问题,但这是我最想回答的一个。 我在任何类型的哈希中也有 0 经验。

我可以轻松使用的唯一编码类型是 base64,它并不是真正的安全性,它只是 dbs 的通用语言。 我试图偏离学习另一种语言只是为了这件事,但我也觉得这肯定可以在我未来的几年里帮助我做其他事情。 这也是我第一次反编译一些东西。

package com.loke.tidy.rest;

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.util.Formatter;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import kotlin.TypeCastException;
import kotlin.jvm.internal.Intrinsics;
import kotlin.text.Charsets;

public final class Signature {
  private byte[] key;

  public Signature(String paramString) {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("");
    stringBuilder.append(paramString);
    stringBuilder.append(":f780e905a457f84ffc7c1d5d953bc0d2");
    this.key = getSha1(stringBuilder.toString());
  }

  private final byte[] createHmac(byte[] paramArrayOfbyte1, byte[] paramArrayOfbyte2, String paramString) {
    SecretKeySpec secretKeySpec = new SecretKeySpec(paramArrayOfbyte2, paramString);
    Mac mac = Mac.getInstance(paramString);
    mac.init(secretKeySpec);
    paramArrayOfbyte1 = mac.doFinal(paramArrayOfbyte1);
    Intrinsics.checkExpressionValueIsNotNull(paramArrayOfbyte1, "mac.doFinal(data)");
    return paramArrayOfbyte1;
  }

  private final String toHexString(byte[] paramArrayOfbyte) {
    Formatter formatter = new Formatter();
    int j = paramArrayOfbyte.length;
    for (int i = 0; i < j; i++) {
      formatter.format("%02x", new Object[] { Byte.valueOf(paramArrayOfbyte[i]) });
    } 
    String str = formatter.toString();
    Intrinsics.checkExpressionValueIsNotNull(str, "formatter.toString()");
    return str;
  }

  public final byte[] getKey() {
    return this.key;
  }

  public final byte[] getSha1(String paramString) {
    Intrinsics.checkParameterIsNotNull(paramString, "text");
    MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
    byte[] arrayOfByte2 = paramString.getBytes(Charsets.UTF_8);
    Intrinsics.checkExpressionValueIsNotNull(arrayOfByte2, "(this as java.lang.String).getBytes(charset)");
    messageDigest.update(arrayOfByte2, 0, paramString.length());
    byte[] arrayOfByte1 = messageDigest.digest();
    Intrinsics.checkExpressionValueIsNotNull(arrayOfByte1, "md.digest()");
    return arrayOfByte1;
  }

  public final String getSignature(String paramString1, String paramString2) {
    Intrinsics.checkParameterIsNotNull(paramString1, "email");
    Intrinsics.checkParameterIsNotNull(paramString2, "timestamp");
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("");
    stringBuilder.append(paramString2);
    stringBuilder.append(':');
    stringBuilder.append(paramString1);
    paramString1 = stringBuilder.toString();
    Charset charset = Charsets.UTF_8;
    if (paramString1 == null)
      throw new TypeCastException("null cannot be cast to non-null type java.lang.String"); 
    byte[] arrayOfByte = paramString1.getBytes(charset);
    Intrinsics.checkExpressionValueIsNotNull(arrayOfByte, "(this as java.lang.String).getBytes(charset)");
    return toHexString(createHmac(arrayOfByte, this.key, "HmacSHA1"));
  }

  public final void setKey(byte[] paramArrayOfbyte) {
    Intrinsics.checkParameterIsNotNull(paramArrayOfbyte, "<set-?>");
    this.key = paramArrayOfbyte;
  }
}```


这似乎是一个用于生成 MAC(消息身份验证代码)的类……松散的数字签名。 API 提供:

  • 使用用户提供的字符串实例化Signature构造函数,该字符串与“幻数”组合并用于生成密钥。

  • 一种为(显然)电子邮件(或电子邮件地址)和时间戳生成签名的公共方法。 签名被编码为十六进制字符串。

  • 用于生成文本的 SHA1 哈希的公共方法。 这是内部使用的。 它可能是无意或故意暴露在 API 中的。

它是如何工作的?

重要的部分只是对标准 Java 加密类的调用; 例如一个 SHA1 摘要创建器和一个 HMAC 生成器。 (HMAC 是基于哈希的 MAC。)您应该能够通过阅读各个类的 javadoc 并将它们与它们的使用方式进行比较来弄清楚发生了什么:

  • java.crypto.Mac (javadoc )
  • javax.crypto.spec.SecretKeySpec ( javadoc )

等等。

可以安全地忽略涉及Intrinsics的神秘事物(IMO)。 看来这段 Java 代码实际上是反编译的 Kotlin 代码。 Intrinsics的调用正在对 Kotlin 参数和值实施各种运行时检查。 例如,我的猜测是对checkExpressionValueIsNotNull的调用将检查第一个参数是否为空。 如果它是null ,它可能会抛出一个异常,其中包含异常消息中的第二个参数。 (您可能会追查这一点,但我怀疑是否值得付出努力。)


这也是我第一次反编译一些东西。

您最好查看原始 Kotlin 源代码。 理解反编译代码通常涉及一定程度的猜测,以确定哪些变量是/均值,并在反编译代码中找出可能的错误和不直观的翻译。 您还需要能够阅读反编译器的目标语言。 在这种情况下,Java。

阅读原始源代码要容易得多。

您已经反编译了作为编译 Kotlin 源代码而不是 Java 源代码的结果的字节码。 基本上这些 Intrinsics 调用检查第一个参数是否为空; 如果是,那么它会抛出一个包含第二个参数的消息的异常。 最好阅读原始源代码而不是尝试在线调试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM