签名
RSA
-
OpenSSL
//生成私钥 $ openssl genrsa -out private.pem 512 Generating RSA private key, 512 bit long modulus ...++++++++++++ ......++++++++++++ e is 65537 (0x10001) //从私钥算出公钥 $ openssl rsa -in private.pem -out public.pem -pubout writing RSA key //查看加密信息 $ openssl rsa -in private.pem -text -out private.txt
- HASH 哈希(散列)函数
- 不可逆(不能用于加密&解密)
- 一个二进制数据,只有一个HASH值
- 非对称 RSA (长度在200位以上的数字)
- 由于是简单的数学计算。所以加密效率比较低…所以一般用于加密核心的(小数据)
- 公钥加密,私钥解密
- 私钥加密,公钥加密
数字签名
-
客户端 消费¥10 发给服务器
-
传递的是二进制。无法保证是否被修改,无法保证安全
- 客户端
- 二进制数据(消费¥10)。HASH算法,得到HASH值
- HASH值,使用公钥通过RSA进行加密
- 再次打包加密(消费¥10+HASH值+公钥加密后的数据)发送。
- 服务端
- 解密得到 (消费¥10+HASH值+公钥加密后的数据)
- 私钥解密取出HASH值A
- 二进制数据(消费¥10)。HASH算法,得到HASH值B
- 如果A!=B 说明数据被篡改。不可用
低级签名
- 签名
- 一个二进制的HASH值进行RSA非对称加密
开发工具:Mac电脑 –> 生成RSA公钥M
- 流程
-
电脑将公钥M以及开发者信息传到服务器 请求证书的过程,通过csr文件申请证书
-
服务器生成证书:对公钥M进行签名 证书=私钥A加密公钥M的HASH值+公钥M
-
本地电脑拿到证书和私钥M关联<点开证书,专用密钥,如果别的电脑需要编译app。把私钥M打成P12>
-
本地app装入手机 私钥M对APP二进制的哈希值签名 APP可执行文件包含:代码、APP签名、证书
-
手机验证 手机取出app证书,公钥A解密得到公钥M,比对HASH值。验证证书是否合法。拿公钥M解密APP签名。判断APP是否被修改过
查看证书 $ cat CertificateSigningRequest.certSigningRequest -----BEGIN CERTIFICATE REQUEST----- MIICejCCAWICAQAwNTEXMBUGCSqGSIb3DQEJARYIYmVhci5jb20xDTALBgNVBAMM BGJlYXIxCzAJBgNVBAYTAkNOMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAwEGOVNltfUUjpI/1MjCR8qsafh7Hyf8nGfpiQgeXYVZBtU/iWIjho+20a3kM wJPzhukIRhNl01kf87oPbIB6CEsBy5k8ijG717v/ov8Nmi9kimb1lzXw0fEJWhZN Nb8yajEDy1w8Gc9rUwYji9jXfqPK9bekCNz/P7NJBATIdp2HYmH1LSGEO6tTB5mN gzHFqCHHdOebFmw0lsy7ZXQObZP34cWLkQxE6W6/4eBViBEb2p/rX4AEve7FQ6ON k1TSTnGDAPArLstXOBO/2n1dNNrmYdI/NBwNrqgXdX9xF9AcoTbMsMDF3eOC1hDw rQ5bukSlMrRWVSlEJCYPhPaZeQIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAELC S8L9mElBMDyHMQdqK8hwbvWYzcViTH6kn8toYkFhWehHpf0Tu3tisu4S1TyJlzyW f/Jum5qj0P1sbO5mKkKUu+iJKCMmcFilUDOzccZ/yIfOi+PjVhvFtFgh4KC95j9y azacdbbzAeszNXwIEOw0+NvvyMOX9AeE94U8i7LjrDEybHuAQs61dSPKNL3xNqD5 oknLKKQ+KcAnRV7wieXNzyVKDzSIJWYl29/JCa5a3plWu4hhylowxlQg2EhBa3sG Xjwnhjn3rqrA3KWriwbddetQRm16bnL7ccFQT12q/M+Ub/pUxGhWQNCapDLPIODs PScodk1iopo+yWU2UR8= -----END CERTIFICATE REQUEST----- 查看证书信息,除了有公钥还有其他信息 $ openssl asn1parse -i -in CertificateSigningRequest.certSigningRequest 0:d=0 hl=4 l= 634 cons: SEQUENCE 4:d=1 hl=4 l= 354 cons: SEQUENCE 8:d=2 hl=2 l= 1 prim: INTEGER :00 11:d=2 hl=2 l= 53 cons: SEQUENCE 13:d=3 hl=2 l= 23 cons: SET 15:d=4 hl=2 l= 21 cons: SEQUENCE 17:d=5 hl=2 l= 9 prim: OBJECT :emailAddress 28:d=5 hl=2 l= 8 prim: IA5STRING :bear.com 38:d=3 hl=2 l= 13 cons: SET 40:d=4 hl=2 l= 11 cons: SEQUENCE 42:d=5 hl=2 l= 3 prim: OBJECT :commonName 47:d=5 hl=2 l= 4 prim: UTF8STRING :bear 53:d=3 hl=2 l= 11 cons: SET 55:d=4 hl=2 l= 9 cons: SEQUENCE 57:d=5 hl=2 l= 3 prim: OBJECT :countryName 62:d=5 hl=2 l= 2 prim: PRINTABLESTRING :CN 66:d=2 hl=4 l= 290 cons: SEQUENCE 70:d=3 hl=2 l= 13 cons: SEQUENCE 72:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption//加密 83:d=4 hl=2 l= 0 prim: NULL 85:d=3 hl=4 l= 271 prim: BIT STRING 360:d=2 hl=2 l= 0 cons: cont [ 0 ] 362:d=1 hl=2 l= 13 cons: SEQUENCE 364:d=2 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption//哈希算法验证 375:d=2 hl=2 l= 0 prim: NULL 377:d=1 hl=4 l= 257 prim: BIT STRING
-
保证开发者的认证和程序的安全性
代码签名原理
- 避免安装滥用的问题,加两个限制
- 限制苹果后台注册过的设备才可以安装,UUID、设备信息
- 签名只能针对某一个app签名
- 描述文件 Provision profile
- 设备IDs
- APPIDs
- ENtitlements<权利文件、授权>
- 安装的时候会跟证书一起打包到app
//文件位置
$ ~/Library/MobileDevice/Provisioning Profiles
//查看描述文件
$ security cms -D -i 8b7156c1-ead4-424f-a402-f3fb5d0b3c2d.mobileprovision
XML文件,加密的
TeamName 团队名称
ExpirationDate 过期时间
AppIDName appID
CreationDate 创建时间
Name
DeveloperCerificates 对应的证书
ProvisionDevices 对应的设备
TimeToLive
ApplicationIdentifierPrefix
IsXcodeManaged
Platform
Version
UUID 描述文件本身UUID
TeamIdentifier
Entitlements
{
get-task-allow 是否允许调试
TeamName
appID
}
-
描述文件在app包里面。本身也是签名认证的无法篡改
-
CodeSignature代码签名信息
-
证书、签名信息在可执行文件里面
-
查看描述文件信息:
$ security cms -D -i 描述文件路径
手动重签
-
查看APP的签名信息
$ codesign -vv -d WeChat.app Executable=~/Desktop/微信-6.6.5(越狱应用)/Payload/WeChat.app/WeChat Identifier=com.tencent.xin Format=app bundle with Mach-O universal (armv7 arm64) CodeDirectory v=20200 size=503759 flags=0x0(none) hashes=15735+5 location=embedded Signature size=4297 Authority=(unavailable)//没有签名 Info.plist=not bound TeamIdentifier=88L2Q4487U Sealed Resources version=2 rules=19 files=822 Internal requirements count=1 size=96 砸过壳,签名被破坏
-
查看本机所有证书
$ security find-identity -v -p codesigning
-
查看可执行文件的加密信息!
$ otool -l WeChat | grep crypt cryptoff 16384 cryptsize 55164928 cryptid 0//加密标识 cryptoff 16384 cryptsize 59457536 cryptid 0//加密标识
重签名:
-
干掉插件Plugins文件夹里面的内容!
-
Watch 直接干掉!
-
对 Frameworks 进行签名! codesign -fs “证书” 需要签名的文件
$ codesign -fs "iPhone Developer: ...... (899ADDGV9B)" MMCommon.framework
-
给可执行文件执行权限!
$chmod +x WeChat
-
拷贝描述文件
-
修改info.plist 的Bundle ID!
-
生成plist的权限文件
//查看权限 $ security cms -D -i embedded.mobileprovision 关注权限字段!!! <<dict>> <<key>>keychain-access-groups<</key>> <<array>> <<string>>C7U6LL8RU9.*<</string>> <</array>> <<key>>get-task-allow<</key>> <<true/>> <<key>>application-identifier<</key>> <<string>>C7U6LL8RU9.*<</string>> <<key>>com.apple.developer.team-identifier<</key>> <<string>>C7U6LL8RU9<</string>> <</dict>>
$ security cms -D -i embedded.mobileprovision
-
签名整个APP!
$ codesign -fs "iPhone Developer: .... (899ADDGV9B)" --no-strict --entitlements=en.plist WeChat.app
9.打包其实就是一个zip
$ zip -ry WeChat.ipa Payload
利用Xcode重签
- 新建项目,Products下xxx.app,ShowinFinder
- 把没有签名信息的app放到ShowinFinder打开的xxx.app下,名字替换,删掉xxx.app
- 干掉插件Plugins文件夹里面的内容!
- Watch 直接干掉!
- 对 Frameworks 进行签名!
- 修改info.plist 的Bundle ID!
- common + R
脚本化自动重签
-
新建项目
-
项目下新建APP文件夹,把ipa丢进去
-
打开Build Phases –> New Run Script Phase,添加脚本
${SRCROOT} 为工程文件所在的目录 TEMP_PATH="${SRCROOT}/Temp" #资源文件夹,放三方APP的 ASSETS_PATH="${SRCROOT}/APP" #ipa包路径 TARGET_IPA_PATH="${ASSETS_PATH}/*.ipa" #存在的先删除 rm -rf "$TEMP_PATH" #新建Temp文件夹 mkdir -p "$TEMP_PATH" # -------------------------------------- # 1. 解压IPA 到Temp下 unzip -oqq "$TARGET_IPA_PATH" -d "$TEMP_PATH" # 拿到解压的临时APP的路径 TEMP_APP_PATH=$(set -- "$TEMP_PATH/Payload/"*.app;echo "$1") # 这里显示打印一下 TEMP_APP_PATH变量 echo "TEMP_APP_PATH: $TEMP_APP_PATH" # ------------------------------------- # 2. 把解压出来的.app拷贝进去 #BUILT_PRODUCTS_DIR 工程生成的APP包路径 #TARGET_NAME target名称 TARGET_APP_PATH="$BUILT_PRODUCTS_DIR/$TARGET_NAME.app" echo "TARGET_APP_PATH: $TARGET_APP_PATH" rm -rf "$TARGET_APP_PATH" mkdir -p "$TARGET_APP_PATH" cp -rf "$TEMP_APP_PATH/" "$TARGET_APP_PATH/" # ------------------------------------- # 3. 为了是重签过程简化,移走extension和watchAPP. 此外个人免费的证书没办法签extension echo "Removing AppExtensions" rm -rf "$TARGET_APP_PATH/PlugIns" rm -rf "$TARGET_APP_PATH/Watch" # ------------------------------------- # 4. 更新 Info.plist 里的BundleId # 设置 "Set :KEY Value" "目标文件路径.plist" /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist" # 5.给可执行文件上权限 #添加ipa二进制的执行权限,否则xcode会告知无法运行 #这个操作是要找到第三方app包里的可执行文件名称,因为info.plist的 'Executable file' key对应的是可执行文件的名称 #我们grep 一下,然后取最后一行, 然后以cut 命令分割,取出想要的关键信息。存到APP_BINARY变量里 APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<` #这个为二进制文件加上可执行权限 +X chmod +x "$TARGET_APP_PATH/$APP_BINARY" # ------------------------------------- # 6. 重签第三方app Frameworks下已存在的动态库 TARGET_APP_FRAMEWORKS_PATH="$TARGET_APP_PATH/Frameworks" if [ -d "$TARGET_APP_FRAMEWORKS_PATH" ]; then #遍历出所有动态库的路径 for FRAMEWORK in "$TARGET_APP_FRAMEWORKS_PATH/"* do echo "🍺🍺🍺🍺🍺🍺FRAMEWORK : $FRAMEWORK" #签名 --force强制签名 /usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" "$FRAMEWORK" done fi