whatsapp 的公钥和私钥怎么提

username StaticPubKey StaticPriKey phone_id
样例:可以找我拿
安卓苹果模拟器都行。价格好商量
q185582795

参考
http://www.xjishu.com/zhuanli/62/202010208090.html

当用户第一次做备份的时候密钥随之产生,但密钥并不会在云端存储,仅仅被保存在智能手机端而且每个手机所产生的密钥都是不同的。因此为了对加密型数据库进行解密,我们必须从创建了备份的智能设备中提取密钥。我们可以从下列位置找到密钥: userdata/data/com.whatsapp/files/key

renrenAPP逆向

.method public static N6(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Landroid/content/Context;Lcom/renren/mobile/android/loginfree/LoginStatusListener;)V
    .locals 1
    .annotation system Ldalvik/annotation/MethodParameters;
        accessFlags = {
            0x10,
            0x10,
            0x0,
            0x0,
            0x0,
            0x10,
            0x10
        }
        names = {
            "account",
            "passwordMd5",
            "isVerify",
            "verifyCode",
            "rkey",
            "context",
            "loginStatusListener"
        }
    .end annotation

    const/4 p2, 0x0

    .line 1
    invoke-static {p2}, Lcom/renren/mobile/android/service/ServiceProvider;->U6(Z)Lcom/renren/mobile/utils/json/JsonObject;

    move-result-object p2

    if-eqz p4, :cond_0

    const-string p3, "rkey"

    .line 2
    invoke-virtual {p2, p3, p4}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V

    :cond_0
    const-string p3, "v"

    const-string p4, "1.0"

    .line 3
    invoke-virtual {p2, p3, p4}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V

    const-string p3, "format"

    const-string p4, "JSON"

    .line 4
    invoke-virtual {p2, p3, p4}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V

    const-string p3, "user"

    .line 5
    invoke-virtual {p2, p3, p0}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V

    const-string p3, "password"

    .line 6
    invoke-virtual {p2, p3, p1}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V

    .line 7
    sget-object p3, Lcom/renren/mobile/android/utils/Variables;->O:Ljava/lang/String;

    const-string p4, "uniq_id"

    invoke-virtual {p2, p4, p3}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V

    const-string p3, "session_key"

    .line 8
    invoke-virtual {p2, p3}, Lcom/renren/mobile/utils/json/JsonObject;->f(Ljava/lang/Object;)V

    const-string p3, "gz"

    const-string p4, "compression"

    .line 9
    invoke-virtual {p2, p3, p4}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V

    const-wide/16 p3, 0x1

    const-string v0, "tab_sequence"

    .line 10
    invoke-virtual {p2, v0, p3, p4}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;J)V

    .line 11
    new-instance p3, Lcom/renren/mobile/utils/json/JsonObject;

    invoke-direct {p3}, Lcom/renren/mobile/utils/json/JsonObject;-><init>()V

    .line 12
    sget-object p4, Lcom/renren/mobile/android/utils/Variables;->J:Ljava/lang/String;

    const-string v0, "station_id"

    invoke-virtual {p3, v0, p4}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V

    const-string p4, "ext_info"

    .line 13
    invoke-virtual {p2, p4, p3}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Lcom/renren/mobile/utils/json/JsonValue;)V

    .line 14
    invoke-static {p2}, Lcom/renren/mobile/android/service/ServiceProvider;->Z4(Lcom/renren/mobile/utils/json/JsonObject;)Ljava/lang/String;

    move-result-object p3

    const-string p4, "sig"

    invoke-virtual {p2, p4, p3}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V

    .line 15
    new-instance p3, Lcom/renren/mobile/android/service/ServiceProvider$2;

    invoke-direct {p3, p6, p0, p1, p5}, Lcom/renren/mobile/android/service/ServiceProvider$2;-><init>(Lcom/renren/mobile/android/loginfree/LoginStatusListener;Ljava/lang/String;Ljava/lang/String;Landroid/content/Context;)V

    .line 16
    new-instance p0, Lcom/renren/mobile/net/http/HttpRequestWrapper;

    invoke-direct {p0}, Lcom/renren/mobile/net/http/HttpRequestWrapper;-><init>()V

    .line 17
    new-instance p1, Ljava/lang/StringBuilder;

    invoke-direct {p1}, Ljava/lang/StringBuilder;-><init>()V

    sget-object p4, Lcom/renren/mobile/utils/ConstantUrls;->t:Ljava/lang/String;

    invoke-virtual {p1, p4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    const-string p4, "/client/login"

    invoke-virtual {p1, p4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    invoke-virtual {p1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object p1

    invoke-interface {p0, p1}, Lcom/renren/mobile/net/INetRequest;->setUrl(Ljava/lang/String;)V

    .line 18
    invoke-interface {p0, p2}, Lcom/renren/mobile/net/INetRequest;->setData(Lcom/renren/mobile/utils/json/JsonObject;)V

    .line 19
    invoke-interface {p0, p3}, Lcom/renren/mobile/net/INetRequest;->setResponse(Lcom/renren/mobile/net/INetResponse;)V

    .line 20
    sget-object p1, Lcom/renren/mobile/android/service/ServiceProvider;->O:Ljava/lang/String;

    invoke-interface {p0, p1}, Lcom/renren/mobile/net/INetRequest;->setSecretKey(Ljava/lang/String;)V

    .line 21
    invoke-static {}, Lcom/renren/mobile/net/http/HttpProviderWrapper;->getInstance()Lcom/renren/mobile/net/http/HttpProviderWrapper;

    move-result-object p1

    invoke-virtual {p1, p0}, Lcom/renren/mobile/net/http/HttpProviderWrapper;->addRequest(Lcom/renren/mobile/net/INetRequest;)V

    return-void
.end method

点击登录按钮执行的分支 登录按钮的RSA方法

private void Q0() {
        RSA.g();
        this.G = this.r.findViewById(R.id.error_hint);
        this.F = this.r.findViewById(R.id.back);
        View findViewById = this.r.findViewById(R.id.welcome_hot_spot_visitor_experience_iv);
        this.E = findViewById;
        findViewById.setOnClickListener(this);
        if (!this.N) {
            this.E.setVisibility(4);
            this.F.setVisibility(0);
        }
        this.F.setOnClickListener(this);
        this.r.findViewById(R.id.telephone_login).setOnClickListener(this);
        this.s = (Button) this.r.findViewById(R.id.planb_login_from_publish_login_btn);
        this.t = (Button) this.r.findViewById(R.id.service_configuration);
        this.z = (EditText) this.r.findViewById(R.id.planb_login_from_publish_account_edt);
        EditText editText = (EditText) this.r.findViewById(R.id.planb_login_from_publish_input_password_edt);
        this.y = editText;
        editText.setTransformationMethod(PasswordTransformationMethod.getInstance());
        this.v = (ImageView) this.r.findViewById(R.id.password_inputtype_change);
        this.u = (TextView) this.r.findViewById(R.id.planb_login_from_publish_forgetpsd_btn);
        this.D = (ViewStub) this.r.findViewById(R.id.third_account_login_enter_bottom);
        P0();
        ProgressDialog progressDialog = new ProgressDialog(getActivity());
        this.H = progressDialog;
        progressDialog.setMessage(RenRenApplication.getContext().getResources().getString(R.string.v5_0_1_guide_register_progress_login));
        if (DebugManager.g()) {
            this.t.setVisibility(0);
            this.t.setOnClickListener(this);
        }
        CheckBox checkBox = (CheckBox) this.r.findViewById(R.id.cb_login_agreement);
        this.w = checkBox;
        checkBox.setVisibility(0);
        TextView textView = (TextView) this.r.findViewById(R.id.tv_login_agreement);
        textView.setVisibility(0);
        AgreementUtils.a.a(textView, getActivity(), this.w);
    }
 

package com.renren.mobile.utils;

import com.baidu.android.common.security.RSAUtil;
import com.xiaomi.mipush.sdk.Constants;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.net.URL;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import kotlin.UByte;

public final class RSA {
    public static String a;
    public static String b;
    public static String c;
    private static String d;
    public static int e;

    private static String a(byte[] bArr) {
        StringBuilder sb = new StringBuilder();
        for (byte b2 : bArr) {
            sb.append(Integer.toString((b2 & UByte.b) + 256, 16).substring(1));
        }
        return sb.toString();
    }

    public static String b(String str, String str2, String str3) throws Exception {
        Cipher instance = Cipher.getInstance(RSAUtil.ALGORITHM_RSA);
        instance.init(1, c(str2, str3));
        return a(instance.doFinal(str.getBytes()));
    }

    private static RSAPublicKey c(String str, String str2) throws Exception {
        try {
            return (RSAPublicKey) KeyFactory.getInstance(RSAUtil.ALGORITHM_RSA).generatePublic(new RSAPublicKeySpec(new BigInteger(str, 16), new BigInteger(str2, 16)));
        } catch (InvalidKeySpecException e2) {
            throw new Exception(e2.getMessage());
        }
    }

    public static String d() {
        return b;
    }

    public static String e() {
        return c;
    }

    public static String f() {
        return a;
    }

    public static void g() {
        new Thread(a.a).start();
    }

    static /* synthetic */ void h() {
        try {
            String i = i();
            d = i;
            if (i != null) {
                b = i.split(Constants.COLON_SEPARATOR)[2].split(Constants.ACCEPT_TIME_SEPARATOR_SP)[0].trim();
                c = d.split(Constants.COLON_SEPARATOR)[3].split(Constants.ACCEPT_TIME_SEPARATOR_SP)[0].trim();
                a = d.split(Constants.COLON_SEPARATOR)[5].split("\\}")[0].trim();
                String str = b;
                b = str.substring(1, str.length() - 1);
                String str2 = c;
                c = str2.substring(1, str2.length() - 1);
                String str3 = a;
                a = str3.substring(1, str3.length() - 1);
            }
        } catch (Exception e2) {
            e2.printStackTrace();
        }
    }

    private static String i() throws Exception {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new URL(" http://login.renren.com/ajax/getEncryptKey").openStream(), "GB2312"));
        String readLine = bufferedReader.readLine();
        bufferedReader.close();
        return readLine;
    }
}

请求回来的数据

{"isEncrypt":true,"e":"10001","n":"aaf27564c44eeadde41e97467137764e415f80c0b1f75ad09be3013980d4cceb","maxdigits":"19","rkey":"f5a0aefc7cf49cacfe0c8c5e149cc0bb"}

得到数据
e是b
n是c
rkey 是a

static /* synthetic */ void h() {
        try {
            String i = i();
            d = i;
            if (i != null) {
                b = i.split(Constants.COLON_SEPARATOR)[2].split(Constants.ACCEPT_TIME_SEPARATOR_SP)[0].trim();
                c = d.split(Constants.COLON_SEPARATOR)[3].split(Constants.ACCEPT_TIME_SEPARATOR_SP)[0].trim();
                a = d.split(Constants.COLON_SEPARATOR)[5].split("\\}")[0].trim();
                String str = b;
                b = str.substring(1, str.length() - 1);
                String str2 = c;
                c = str2.substring(1, str2.length() - 1);
                String str3 = a;
                a = str3.substring(1, str3.length() - 1);
            }
        } catch (Exception e2) {
            e2.printStackTrace();
        }
    }

密码和账号

s是密码

Variables.r = this.z.getText().toString().trim();
 Variables.s = this.y.getText().toString().trim();
 q = RSA.f();
            this.P = RSA.e();
            String d = RSA.d();
            this.Q = d;
            if (q != null) {
                try {
                    Variables.s = RSA.b(Variables.s, this.P, d);
                    RSA.e = 1;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                Variables.s = Md5.toMD5(Variables.s);
                RSA.e = 2;
            }
            String str4 = Variables.r;
            if (str4 != null && str4.length() > 0 && (str = Variables.s) != null && str.length() > 0) {
                if (this.I == null) {
                    BaseActivity activity = getActivity();
                    Objects.requireNonNull(activity);
                    Dialog dialog = new Dialog(activity);
                    this.I = dialog;
                    dialog.setContentView(R.layout.login_dialog);
                }
                this.I.show();
                if (RSA.e != 1) {
                    q = null;
                }
                ServiceProvider.N6(Variables.r, Variables.s, 1, "", q, getActivity(), this.R);


MD5算法
public static String toMD5(String str) {
        if (str == null) {
            return null;
        }
        try {
            return d(str.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }


return d 算法部分
private static synchronized String d(byte[] bArr) {
        String sb;
        synchronized (Md5.class) {
            try {
                MessageDigest instance = MessageDigest.getInstance("MD5");
                instance.update(bArr);
                byte[] digest = instance.digest();
                StringBuilder sb2 = new StringBuilder();
                for (byte b : digest) {
                    sb2.append(Integer.toHexString((b & UByte.b) | InputDeviceCompat.u).substring(6));
                }
                sb = sb2.toString();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
                return null;
            }
        }
        return sb;
    }



api_key 直接写死9e1874c67e0b42d79cc16f787b644339

 public static final String M = RenRenApplication.getContext().getResources().getString(R.string.apikey);
str4是q,往回倒

 if (str4 != null) {
            U6.put("rkey", str4);
        }

 q = RSA.f();

 public static String f() {
        return a;
    }


a = d.split(Constants.COLON_SEPARATOR)[5].split("\\}")[0].trim();
String str3 = a;
a = str3.substring(1, str3.length() - 1);
sig

 U6.put("sig", Z4(U6));

 private static String Z4(JsonObject jsonObject) {
        String[] keys = jsonObject.getKeys();
        StringBuilder sb = new StringBuilder();
        Vector vector = new Vector();
        for (String str : keys) {
            String jsonValue = jsonObject.getJsonValue(str).toString();
            sb.append(str);
            sb.append('=');
            sb.append(URLEncoder.encode(jsonValue));
            sb.append(Typography.c);
            if (jsonValue.length() > 50) {
                jsonValue = jsonValue.substring(0, 50);
            }
            vector.add(str + ContainerUtils.KEY_VALUE_DELIMITER + jsonValue);
        }
        String[] strArr = new String[vector.size()];
        vector.copyInto(strArr);
        return Y4(strArr, O);
    }

 public static String Y4(String[] strArr, String str) {
        for (int i2 = 0; i2 < strArr.length; i2++) {
            for (int length = strArr.length - 1; length > i2; length--) {
                int i3 = length - 1;
                if (strArr[length].compareTo(strArr[i3]) < 0) {
                    String str2 = strArr[length];
                    strArr[length] = strArr[i3];
                    strArr[i3] = str2;
                }
            }
        }
        StringBuffer stringBuffer = new StringBuffer();
        for (String str3 : strArr) {
            stringBuffer.append(str3);
        }
        stringBuffer.append(str);
        return Md5.toMD5(stringBuffer.toString());
    }

u6的算法

    public static JsonObject V6(boolean z2, boolean z3) {
        JsonObject jsonObject = new JsonObject();
        jsonObject.put(NotifyType.VIBRATE, "1.0");
        jsonObject.put(Constants.q, M);
        jsonObject.put("call_id", System.currentTimeMillis());
        if (!z2 && !TextUtils.isEmpty(Q)) {
            jsonObject.put("session_key", Q);
            Log.d("zxc", "session " + Q);
        }
        i(jsonObject, z3);
        return jsonObject;
    }
第二个sig  由此可以看出secretkey和前面所有的字段组成MD5

 public void setSecretKey(String str) {
        this.B = str;
    }

 public String p() {
        return this.B;
    }


 static {
        String string = RenRenApplication.getContext().getResources().getString(R.string.secretkey);
        O = string;
        P = string;
    }


public String t() {
        if (this.q == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        int i = this.u;
        if (i == 6 || i == 7) {
            sb.append(this.q.getString(RemoteMessageConst.MSGBODY));
        } else {
            String[] keys = this.q.getKeys();
            if (keys == null || keys.length == 0) {
                return "";
            }
            Vector vector = new Vector();
            for (String str : keys) {
                String jsonValue = this.q.getJsonValue(str).toString();
                sb.append(str);
                sb.append('=');
                sb.append(URLEncoder.encode(jsonValue));
                sb.append(Typography.c);
                if (jsonValue.length() > 50) {
                    jsonValue = jsonValue.substring(0, 50);
                }
                vector.add(str + ContainerUtils.KEY_VALUE_DELIMITER + jsonValue);
            }
            String[] strArr = new String[vector.size()];
            vector.copyInto(strArr);
            String str2 = this.B;
            if (!(str2 == null || str2.length() == 0)) {
                sb.append("sig=");
                sb.append(ServiceProvider.Y4(strArr, this.B));
            }
        }
        return sb.toString();
    }


可以参考这个

img

私钥保存的目录,现在无法读取了(如果有android低版本的手机有可能成功)
需要用手机号登录之后才会生成密钥,但是模拟器无法用手机号登录...

https://www.anquanke.com/post/id/85330
https://3g.163.com/dy/article/E5GNN7VU0511CJ6O.html?spss=adap_pc