原文成于2019年
密码学概念
- 对称加密
- 需要 private 通道传递密钥.
- 非对称加密
- 实现 encryption (保证发送的东西没有别人知道): 传递方用接收方发布的公钥加密, 接收方用私钥解密.
- 实现 authentication (保证发送的人不会是别人): 传递把 message 用自己的私钥加密, 作为 signature 和 message 一起发给接收方, 接收方收到后用传递方早前公开提供的公钥对 signature 进行解密, 验证能还原到 message.
- 混合加密: 用对称秘钥加密明文, 并用非对称秘钥加密对称秘钥.
互联网中的 Certificate Authority
如果传递方只发送 public key 和 signature, 有一个隐患, 就是中间者攻击. 如果发送方和接收方之前没有任何通信过, 中间者可以使用自己的 private/public key, 全程把拦截到的信息转发给接收方, 让接收方误以为自己是发送方. 关键问题是要有一个机制, 让中间者无法把 public/private key pair 替换掉.
- 使用证书, 传递方把自己的证书一起发送. 证书实际上是 authentication 的应用: 证书包含一些用 private key 加密的数据. 接收方可以验证 public key 和证书是对应的.
- 中间者拦截到真正的证书后, 如果选择向发送方透传这个包含真的 public key 的证书, 他就无法达到他的非法目的. 因为一旦这样, 整个通信过程就会使用这个证书的 key pair, 中间人就无法作假.
- 中间者如果选择发送自己设法伪造的证书, 就不可能不被察觉. 因为接收方有办法发觉这个证书的伪造之处.
- 要确定证书是正当的还是伪造的, 关键在于需要有权威机构签发 (issue) 证书.
- 世界上有可以数尽的根认证机构, 其各有自认证的根证书.
- 这些公司按树型关系逐级会签发证书给别的机构, 子证书和父证书的所属关系是可以合法验证的, 造假者不可能自己单独建一个假的子证书关联到父证书.
- 验证某个子证书是由父证书签发, 同样也是 authentication 的应用: 验证者可以使用父证书公开的 public key 在本地确认是否可以正确 decrypt 子证书.
- 软件公司在自己的 Browser/Operating System 中加入最顶级的根证书
- 当收到发送方传来的证书时, 按照链式关系验证证书是否最终会导向根证书, 如果 ok 则信任, 否则交由用户处理(称之为自认证证书).
- 互联网证书系统实际上是把"public key公开"这一步, 转移到以权威机构签发证书, 来解决问题.
日常开发中的 Charles, 正是中间人攻击的一种正面应用.
- Charles 自己有自己的 root 证书.
- 在检测到对某个域名的访问时, Charles 会针对该域名基于 root 证书现场创建一个子证书, 并把该证书提供给发送方设备.
- 设备需要手动信任该证书.
- 也可以提前把 Charles 的 root 证书添加到信任列表.
- 发送方设备使用 Charles 的证书对应的 public key 加密后, Charles 有能力 decrypt, 并用真正的服务端 public key 重新加密, 发送给服务端.
操作系统中的 chmod & chown
unix下每个文件都有3类不同的访问者: user, group, other.
对每类访问者都支持三种不同操作: read, write, execute
- chmod: 用来改变文件针对不同访问者的访问权限
- chown: 用来改变文件所属的user
Xcode 下 build 时自动化把文件拷贝到受限目录
- 增加 copy file phase. 无法解决"permission denied"问题.
- 依赖 Deployment 设置中的 installation location. 不一定能满足需求, 因为它会在目标位置建立完整的目录, 也会面临permission问题.
- 目前找到的唯一的办法: 使用 custom script phase, 里面用
sudo cp
来解决.- 但是 Xcode 执行 script 的环境默认不支持 sudo, 也不可能交互式地输入密码, 所以需要用
sudo -A
指定一个 password 输出程序. - 这个文件可以直接用shell写, 内容是
echo password
即可, 但注意这个文件需要对 xcode 而言有 x 权限
- 但是 Xcode 执行 script 的环境默认不支持 sudo, 也不可能交互式地输入密码, 所以需要用
Case: Mac OS Privilege Jobs
我们的 mac app 经常需要临时获得特权来访问一些受保护的系统资源. 当然需要由用户的确认, 但我们又不想把整个 app 权限提的太高. 因此可以使用2个进程, 一个 daemon , 一个 main app. Main app 把 daemon 作为 privilege helper tools 注册给系统, 系统(经过用户确认)安装到位后, 两者进行 IPC 传递数据.
相关 frameworks:
- Security - Authorization Services: 权限相关的定义.
- ServiceManagement: 注册privilege tools.
- XPC: 用于轻量级的进程间通信.
(注: 不建议再使用AuthorizationExecuteWithPrivileges, 此方法因为没有对待启动的tool作更严格的校验, 已被标记deprecated.)
这些库用到了的 mac 系统技术有:
- launchd: 管理系统daemon和agent的启动.
- launchctl: 可以解析相关service的plist.
参考: