React Native 打包签名方案

React Native 打包签名方案

@Allen fengjun.dev@gmail.com

我们都知道,RN开发完成后,不管是集成到app中一起发布还是热更新发布,都会涉及到js代码的打包。如果代码中引用了静态图片资源,还需要连同图片一起打包。除此以外,还要想办法保证我们所执行的js代码的安全性和完整性,基于这些需求,我们形成了一套RN打包签名的方案,本文主要对这套方案记录,以供参考。

静态图片加载方式的选择

根据官方文档,加载静态图片资源一共有两种方式。第一种是将图片放置在原生app的res/drawable目录中,然后在js代码中使用下面方式加载:

<Image source={{uri: 'app_icon'}} style={{width: 40, height: 40}} />

但是这样的方式并不优雅,不仅会增大宿主APP的体积,还会导致js层的实现与原生层耦合在一起,当热更新时无法做到图片的更新。

第二种方式是采用相对路径的方式进行加载,例如,我们有以下的目录结构

src
├── button.js
└── img
    ├── check.png
    └── check_pressed.png

然后在button.js这样引用:

<Image source={require('./img/check.png')} />

这样的方式就比较灵活,只要将js代码和使用到的图片打包在一起,就可以在热更新的时候做到业务代码和图片的同步更新。

所以我们在项目中统一采用的第二种方案去加载静态图片。

对图片路径的定制

我们希望打包时,整个RN包内部是下面的结构,将所有图片放置在images目录下,这样的目录结构比较清晰明了

├── images
│   ├── drawable-hdpi
│   ├── drawable-mdpi
│   ├── drawable-xhdpi
│   ├── drawable-xxhdpi
│   └── drawable-xxxhdpi
└── index.android.bundle

但是这里有个问题,release版本中,RN采用require方式加载图片时,生成的路径是下面的形式:

<bundle当前路径>/drawable-mdpi/foldername_imagename.png

根据上面打包的结构,需要定制成为以下的形式才能正确访问到图片:

<bundle当前路径>/images/drawable-mdpi/foldername_imagename.png

所以就涉及到了对图片路径定制的需求,经过RN源码的探索,发现对于图片路径的解析是由node_modules/react-native/Libraries/Image/resolveAssetSource.js来完成的,解析生成图片路径主要代码如下:

/**
 * `source` is either a number (opaque type returned by require('./foo.png'))
 * or an `ImageSource` like { uri: '<http location || file path>' }
 */
function resolveAssetSource(source: any): ?ResolvedAssetSource {
  if (typeof source === 'object') {
    return source;
  }

  var asset = AssetRegistry.getAssetByID(source);
  if (!asset) {
    return null;
  }

  const resolver = new AssetSourceResolver(getDevServerURL(), getBundleSourcePath(), asset);
  if (_customSourceTransformer) {
    return _customSourceTransformer(resolver);
  }
  return resolver.defaultAsset();
}

function setCustomSourceTransformer(
  transformer: (resolver: AssetSourceResolver) => ResolvedAssetSource,
): void {
  _customSourceTransformer = transformer;
}

可以看到,我们可以通过调用setCustomSourceTransformer来设置自己的AssetSourceResolver来完成自定义的路径解析生成器,加上需要的images这一部分路径即可。

Bundle打包和图片导出

主要是使用官方提供的react-native bundle命令实现这个过程,如

react-native bundle --entry-file index.android.js --bundle-output ./output/my.bundle --dev false --platform android --assets-dest ./output/images/

具体的参数可以通过--help查看说明,需要注意的是,assets-dest指定的就是js代码中引用到的图片资源的导出路径,如果不指定,将不会导出图片。

命令执行完成后,output目录下:

├── images
│   ├── drawable-hdpi
│   ├── drawable-mdpi
│   ├── drawable-xhdpi
│   ├── drawable-xxhdpi
│   └── drawable-xxxhdpi
└── index.android.bundle

签名与打包

在完成了上面的操作后,我们只是得到了一个文件夹,里面包含了bundle文件和图片文件,如果涉及到中间人攻击,bundle文件可能会被篡改,安全无法得到保证,所以我们需要对这个文件夹下的文件进行加签处理。具体采用的是下面的签名方案:

React Native 打包签名方案

(1)生成MANIFEST.MF文件:这是摘要文件。遍历build目录所有文件(entry),对非文件夹、非签名文件的文件,逐个使用SHA1生成摘要信息,再用Base64编码。并在摘要文件头部写入bundle的版本信息等。

说明:如果有人改变了安装包中的文件,那么在安装校验的时候,改变后的文件摘要信息与MANIFEST.MF的校验信息不同,将无法安装。但是,如果攻击者重新生成了摘要文件,就可以通过验证,所以这只是一个非常简单的验证。需要结合(2)确保安全性。

(2)生成CERT.SF文件:这是摘要文件的签名文件。对前一步生成的MANIFEST.MF,使用SHA1-RSA算法,用私钥进行签名。在安装时,在客户端使用公钥进行解密,解密之后MANIFEST.MF的内容进行比对,如果相符,则表明内容没有被异常修改。

说明:在这一步,即使攻击者修改了内容,并生成了新的摘要文件,但是攻击者没有开发者的私钥,所以不能生成正确的签名文件(CERT.SF)。客户端在对安装包进行验证的时候,用公钥对不正确的签名文件进行解密,得到的结果和摘要文件(MANIFEST.MF)对应不起来,所以不能通过检验,不能成功安装文件。从而确保了安全性。

完成上述流程后,将签名文件和bundle等文件一起压缩,就完成了整个打包的流程。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容