今天来介绍,数位凭证,讲一点点数位签章,以及最重要的凭证绑定原理及用途
避免有人透过手机使用 Burp Suite 或 Charles 拦截,即可发现凭证内容不符合,而拒绝连线进而达到保护的目的
一般我们在说的网页用凭证 SSL / TLS 凭证,也称为 数位凭证(digital certificate)用来证明公开金钥拥有者的身分。
此档案包含了公钥资讯、拥有者身分资讯(主体)、以及数位凭证认证机构(发行者)
且对这份档案做了数位签章,确保档案内容正常没有问题
数位签章(英语:Digital Signature,又称公钥数位签章)
数位签章是能够实现『身分鉴别』和『检查讯息完整性』两种功能的讯息鉴别码 外也加入了不可抵赖性机制
作法可看前面的『讯息鉴别码』章节,加密流程相同,差别采用公开金钥机制,因此可以确定讯息的制作者
数位凭证就是用来确保使用者使用的服务器凭证是服务器提供的
为了确保是咩的公钥,需要跟凭证机构(certification authority) CA 申请发行凭证证明金钥 P咩 是咩的
凭证机构机构本身也具有自己的公开金钥PCa 及私密金钥Sca
接下来 咩 将自己的,个人资讯加上公开金钥,传送给凭证机构
凭证机构确认过资讯後,使用凭证机构的 私密金钥 Sca 进行签章
凭证机构将制作完成的数位签章跟数据合成一个电子档
最後凭证机构把电子档案传回给 咩,这个电子档就是咩的数位凭证
咩接着就可以传送自己的数位凭证,取代只有传送公钥
使用者/客户端进行动作确认凭证有效
凭证用途非常的广,国人使用的自然人凭证,工商凭证,健保卡等都是属於数位凭证的用途
另外我们使用再服务器尚的数位凭证又称为『服务器凭证』、HTTPS/SSL凭证
下图为维基百科的凭证(数位凭证)
得知以下资讯
可以整理出 wikipedia.org 网域,使用 ecc - secp256r1 公钥 ,并且透过 Let's Encrypt 将这些资讯进行签章
当我们已经使用数位凭证再我们的Server上为什麽还需要凭证?
因为原本方式只能确保服务器的公钥是服务器原始提供的
并无法确认,客户端/使用者是否有进行凭证的验证
先前的章节提过我们可以使用公开金钥系统对资料进行保护,看起来万无一失,但黑客却不直接对演算法进行攻击,而是使用窃听(eavesdrop)和电子欺骗(spoofing)方式进行伪装
这方式又称为 中间人攻击(Man-in-the-middle attack,MITM)
取代掉原本的数位凭证,使用者端若是没有进行验证将会被劫持传输的内容
在处理方式上,普遍是使用凭证绑定 (certificate pinning) 的方式,把需要比对的凭证预先存放在应用程序里,等要进行 SSL Handshake 的时候再与服务器的凭证做比对。
当遇到有被取代掉的凭证,使用者用了 Burp Suite 或 Charles 想要拦截流量,由於凭证会更换为Burp或Charles
我们APP再进行连线时,即可发现凭证内容不符合,而拒绝连线进而达到保护的目的
import Alamofire
//自定 manager
fileprivate static var manager: Alamofire.SessionManager = {
// Create custom manager
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
return Alamofire.SessionManager(
configuration: configuration,
serverTrustPolicyManager: CustomServerTrustPoliceManager()
)
}()
class CustomServerTrustPoliceManager : ServerTrustPolicyManager {
//自订信任协议
override func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? {
//如果网域符合
if host.hasSuffix("www.example.com") {
//从档案资料夹取出凭证
let dir_bundle:Bundle = Bundle.init(path: "/certificates")!
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
//进行比对的参数
certificates: ServerTrustPolicy.certificates(in:dir_bundle),
validateCertificateChain: true,
validateHost: true
)
return serverTrustPolicy
}
return .performDefaultEvaluation(validateHost: true)
}
public init() {
super.init(policies: [:])
}
}
Android 新的OS 可以使用网络安全配置 功能,可以直接使用此功能定义网路安全设定,而无需使用程序码
res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">example.com</domain>
<pin-set expiration="2018-01-01">
<pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
<!-- backup pin -->
<pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin>
</pin-set>
</domain-config>
</network-security-config>
或是使用程序码的方式,将金钥放入KeyStore,再连线的时候进行比对
KeyStore keyStore = ...;
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
URL url = new URL("https://www.example.com/");
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
Android 跟 iOS 系统本身内无法直接像 Http 请求可以直接设定凭证绑定验证
但可以自己实作,可以拦截请求连线,改成自己定义Http连线,并检查凭证是否有检验通过
https://developer.android.com/training/articles/security-config.html#CertificatePinning
https://owasp.org/www-community/controls/Certificate_and_Public_Key_Pinning
https://devco.re/blog/2014/08/15/ssl-mishandling-on-mobile-app-development/
https://developer.android.com/training/articles/security-ssl.html#UnknownCa
<<: 寻觅 webpack - 28 - 真实世界的 webpack - 配置多模式专案
>>: 2020it邦铁人赛-30天手把手的Vue.js教学 Day30 - 关心时事! 做个简单的COVID-19追踪app吧!(下)
MyBatis前导 ...
本篇文章同步发表在 HKT 线上教室 部落格,线上影音教学课程已上架至 Udemy 和 Youtu...
现在我们来介绍 EC2 里面的 Instance Storage 与 EBS 的差别,那我们开始吧...
练习使用selenium来登入FB from selenium import webdriver d...
经过了连续5篇复杂度略高的物理模拟系列,我在想看官们多少会有点疲乏~ 所以我在规划了几篇『中场休息』...