Android-Java证书签名获取、代码运行时校验、鉴权

48 篇文章 2 订阅
1 篇文章 0 订阅

证书等的概念

相关概念连接
简单说:

  • keystore就是数据库,存着 证书(Certificate)
  • 证书
    • 拥有人的信息(公司、住址、电话、官网)
    • 公钥(Public Key)
    • 证书的签名(MD5、SHA1、SHA256,各种摘要算法)
    • AC机构(该证书授权的机构)

获取证书指纹

  • 从KeyStore里获取证书
//keytool 是JDK jre\bin下的执行文件
//从keystore中导出证书
keytool -export -keystore you-keystore -alias you-alias -file Example.cer
//获取证书中的信息
keytool -printcert -file Example.cer
  • 从APK包里获取证书
    • 取出APK中meta-info/CERT.RSA (将APK后缀改成zip,解压缩就行,CERT.RSA就是证书)
    • 运行 keytool -printcert -file CERT.RSA (keytool是JDK bin下的可执行文件,需要在环境变量path中才能运行)

打印出來的信息

    证书指纹:
     MD5: CB:38:17:D9:44:74:EE:.......
     SHA1: 28:3D:60:DD:C.......
     SHA256: BC:C3:5D:......
     签名算法名称: SHA1withRSA

Android运行时获取

public class SignatureUtils {
    private static final String TAG = "SignatureUtils";

    public static String[] getSha1And256(Context context) throws PackageManager.NameNotFoundException {
        String[] sha = new String[2];
        PackageInfo packageInfo = context.getPackageManager().getPackageInfo(
                context.getPackageName(), PackageManager.GET_SIGNATURES);
        //note sample just checks the first signature
        if (packageInfo.signatures != null && packageInfo.signatures.length > 0) {
            sha[0] = getSHA1(packageInfo.signatures[0].toByteArray());
            sha[1] = getSHA256(packageInfo.signatures[0].toByteArray());

            return sha;
        }

        return null;
    }

    //computed the sha1 hash of the signature
    private static String getSHA1(byte[] sig) {
        return getMessageDigest(sig, "SHA1", "BC");
    }
    private static String getSHA256(byte[] sig) {
        return getMessageDigest(sig, "SHA-256", null);
    }

    private static String getMessageDigest(byte[] sig, String algorithm, String provider) {
        String sha1 = null;
        MessageDigest shaDigest;
        try {
            if (provider == null) {
                shaDigest = MessageDigest.getInstance(algorithm);
            } else {
                shaDigest = MessageDigest.getInstance(algorithm, provider);
            }
            shaDigest.update(sig);
            byte[] hashtext = shaDigest.digest();
            sha1 = bytesToHex(hashtext);
            LogUtil.i(TAG, "SHA" + algorithm + ": " + sha1);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        }
        return sha1;
    }

    //util method to convert byte array to hex string
    private static String bytesToHex(byte[] bytes) {
        final char[] hexArray = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
                '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        char[] hexChars = new char[bytes.length * 2];
        int v;
        for (int j = 0; j < bytes.length; j++) {
            v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }
}

PackageInfo.signature

packageInfo.signatures是一个Array,但实际上APK往往都是1个证书签名的。AndroidStudio提醒是有的人可能含有两个证书,一个伪造的,一个真正的证书。这样我们验证就可能出错,暂时没考虑这么多了。

Public Key

signature 是有getPublicKey,不过是hide注解了,只能FrameWork用。只能自己写getPublicKey,如下是原生方法

    /**
     * Returns the public key for this signature.
     *
     * @throws CertificateException when Signature isn't a valid X.509
     *             certificate; shouldn't happen.
     * @hide
     */
    public PublicKey getPublicKey() throws CertificateException {
        final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        final ByteArrayInputStream bais = new ByteArrayInputStream(mSignature);
        final Certificate cert = certFactory.generateCertificate(bais);
        return cert.getPublicKey();
    }
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值