在我的应用程序中固定公钥

Posted

技术标签:

【中文标题】在我的应用程序中固定公钥【英文标题】:Pinning public key in my app 【发布时间】:2015-04-24 09:50:40 【问题描述】:

作为安全措施的一部分,我将公钥固定在我的应用程序中,因为我从我的 PEM 证书中提取了公钥,看起来像

-----BEGIN PUBLIC KEY-----
MIIBIj....IDAQAB
-----END PUBLIC KEY-----

然而,在 OWASP 的示例代码中,我们确实看到了比较 DER 编码的公钥的代码,

// DER encoded public key
private static String PUB_KEY = "30820122300d06092a864886f70d0101"
+ "0105000382010f003082010a0282010100b35ea8adaf4cb6db86068a836f3c85"
+ "5a545b1f0cc8afb19e38213bac4d55c3f2f19df6dee82ead67f70a990131b6bc"
+ "ac1a9116acc883862f00593199df19ce027c8eaaae8e3121f7f329219464e657"
+ "2cbf66e8e229eac2992dd795c4f23df0fe72b6ceef457eba0b9029619e0395b8"
+ "609851849dd6214589a2ceba4f7a7dcceb7ab2a6b60c27c69317bd7ab2135f50"
+ "c6317e5dbfb9d1e55936e4109b7b911450c746fe0d5d07165b6b23ada7700b00"
+ "33238c858ad179a82459c4718019c111b4ef7be53e5972e06ca68a112406da38"
+ "cf60d2f4fda4d1cd52f1da9fd6104d91a34455cd7b328b02525320a35253147b"
+ "e0b7a5bc860966dc84f10d723ce7eed5430203010001";

我知道 DER 是一种二进制格式,但不确定作者如何转换或提取上述格式?当我转换为 DER 时,它的原始字节与上述格式不同。 有没有人指点这个?

替代方法可以是, 示例代码,

//Hack ahead: BigInteger and toString(). We know a DER encoded Public Key begins
//with 0x30 (ASN.1 SEQUENCE and CONSTRUCTED), so there is no leading 0x00 to drop.
RSAPublicKey pubkey = (RSAPublicKey) chain[0].getPublicKey();
String enc

oded = new BigInteger(1 /* positive */, pubkey.getEncoded()).toString(16);

如果我转换“编码”变量 base64 PEM 公钥格式。如何在 android 中做到这一点?

任何帮助将不胜感激

【问题讨论】:

参考。 ***.com/questions/11787571/… 嘿托尼,我正在尝试在 SSL 握手时读取服务器的公钥。您提到的代码说明了如何从静态 PEM 文件中读取公钥(以防我捆绑在应用程序中)。 SSL 握手时我有 X509Certificate 实例,我想将其转换为 PEM 公钥 base 64 格式,或者我的应用程序中有 PEM base64 公钥并希望将其转换为 ASN1 DER 编码。 如果您只是尝试将固定作为一种安全措施,那么实现它的方法是使用自定义的 TrustManager - *** 上已经有很多关于此的问题(例如***.com/questions/5170279/…)。如果您确实需要阅读服务器证书,那么***.com/questions/11143360/… Tony,第一个链接解释了如何验证 SSL 证书是否可信。如果服务器有任何 CA 签名证书,则此代码将起作用。第二个链接,是的,这是我想做的,但正如 OWSP 链接所解释的那样。不是通过包含完整的 PEM 证书并添加到信任库。如果您阅读了我的问题,我向这两个链接没有帮助的 2 种方法寻求帮助。顺便说一句 - 我对堆栈流做了足够的研究,然后提出了这个问题,我确实看到了很多相关的线程,但没有回答我的要求。 @Pankaj 我也有同样的要求,我获取了我的公钥,看起来像 00 01 10 00 00 00 00 E0 I0 00 00 00 00 00 00 00 00 00 所以请让我知道我应该怎么做做进一步的过程。我的意思是服务器通信。请指导我。我参考github.com/riramar/pubkey-pin-android 【参考方案1】:

下面一行解决了我的问题:

String base64Encoded = Base64.encodeToString(pubkey.getEncoded(), Base64.DEFAULT).
    replaceAll("\n", "");

【讨论】:

感谢您的解决方案。我整天都在谷歌上寻找如何正确解码,这拯救了我的一天。例如,我修改了找到的原始应用程序并将其上传到 github。你可以在这里找到它:github.com/jiahaoliuliu/pubKeyPinningInAndroid/blob/master/app/… 这需要更多 + 票。如果您使用任何 Android 5.x 设备,则需要它。 RSA 检查代码还应该检查 authType 字符串是否包含“RSA”而不是等于它...

以上是关于在我的应用程序中固定公钥的主要内容,如果未能解决你的问题,请参考以下文章

如何在 DraggableScrollableSheet 小部件中固定前两个最顶部的小部件?

滚动时如何在 UIScrollView 中固定图像/视图

使用 Microsoft Azure SDK 在 iOS 中固定 SSL 证书

WPF界面开发:DevExpress WPF在GridControl中固定行时处理时刻

如何在 Mac 催化剂中固定窗口的位置?

如何修复 extjs 网格中固定的水平滚动条?