前言
为了更好地理解Android APK的JAR Signing v1签名机制,专门了解JAR文件签名的相关说明。
译文的情况如下:
- 章节目录与文档保持一致,但段落断句稍有区别。
- 有部分我认为是专用名词,不会对其进行翻译,以便在阅读英文原文时候重点辨认和理解,例如:
security
,versioning
,headers
,attributs
等。
正文
介绍
JAR文件,使用主流的ZIP文件格式,并整合多个文件为的一种格式。
一个JAR文件本质上就是ZIP文件,可选地包含一个META-INF目录。
在Java平台可以通过 jar
工具,或者使用 java.util.jar
API 创建一个JAR文件。
JAR的文件名并没有格式限制,只要符合一般性的文件命名规范即可。
大部分情况下,JAR文件不仅仅只有 .class
文件或资源文件,往往是作为组成一个应用或应用扩展的一部分。
只要JAR文件内存在META-INF
目录,该目录内用作放置包和扩展的配置数据
,包括security
,versioning
,extension
,services
。
META-INF目录
META-INF
目录中的文件或子目录,会被Java 2识别并配置 applications
,extensions
,类加载器
和services
。
- MANIFEST.MF
manifest文件是用作定义扩展和包相关的数据。
- INDEX.LIST
这个文件通过jar
工具的"-i"命令参数创建。它包括一个包路径信息。作为JarIndex
实现的一部分,能加快类加载器的加载速度。
- x.SF
这是JAR文件的签名文件
,‘x’代表文件名。
- x.DSA
这是签名块文件
,与签名文件
通过相同文件名进行对应。
- services/
该目录保存所有service
提供者的配置文件。
Name-Value对和Sections
在我们开始了解上述配置文件细节前,需要阐明本规范文档一些格式转换规则。
在大部分情况下,manifest文件
和签名文件
中的信息,都会按照RFC882标准
规范的名为"name: value对
"(后面简称名值对
)的形式编写,又或者称为headers
或者attributes
。
多个名值对
构成的组群,称为section
。多个 Sections 之间通过空行进行分割
所有的文件二进制数据都会转为 base64
字符串的格式。如果长度超过了72个字节,需要连续不能截断。二进制数据的样例都是数字摘要和签名。
所有实现需要支持headers
值上限65535字节长度。
本文件中的所有规范都使用相同的语法,其中终端符号以固定宽度的字体显示,非终端符号以斜体字表示。
文档规范说明:
原文内容:
section: header +newline
nonempty-section: +header +newline
newline: CR LF | LF | CR(not floowed by LF)
header: name:value
name: alphanum *headerchar
value: SPACE *otherchar newline *continuation
continuation: SAPCE *otherchar newline
alphanum: {A-Z|a-z|0-9}
headerchar: alphanum | - | _
otherchar: any UTF-8 character except NUL, CR and LF
; Also: To prevent mangling of files sent via straight e-mail, no
; header will start with the four letters "From".
译文:
-
section
节信息 = (头信息
+ 1..*个换行
) -
nonempty-section
非空的节信息= (1..个头信息
+ 1..个换行
) -
newline
换行符 = (可使用:回车换行
'\r\n' 或换行
'\n' 或回车
'\r'(但后面不能是换行符)) -
header
头信息 =名值对
-
name
"名值对"的名 =英文数字
+ 0..*个合规首字符
-
value
"名值对"的值 =空格
+ 0..个字符 + 1个换行符
+ 0..个值的延续部分
-
continuation
值的延续部分 =空格
+ 0..*个字符 + 1个‘换行符’ -
alphanum
英文数字 = {A-Z|a-z|0-9} -
headerchar
合规首字符 =英文数字 或者
"短折线"或者
“下划线”` -
otherchar
= 不为NUL
、回车符号
、换行符号
的任意UTF-8
编码格式的字符
还有:为了阻止零碎文件通过不间断的email发送,头信息
不能以"From",这四个字母开头
上述定义的非终端符号
规范,会在下文中使用。
JAR清单(Manifest)文件
概述
一个JAR文件的清单内容组成:一个主section
开头,一组sections列表
分别对应单个JAR实体文件。主section
和 sections列表
都遵从上述的关于section 节信息
语法,有各自的限制和规则。
主section
包含:
- 单个JAR文件、一个应用包或一个扩展包文件自身的安全与配置信息
- 每个独立清单实例中,要应用的主要属性
- 该section不能使用'name'作为名字的属性。
- 使用空行作为本section内容的结尾
sections列表
:
- JAR文件中包或子文件对应的清单内容使用的各种属性。
- 所有要被签名的文件,都必须列出。
- 这个清单文件
本身,一定不能在列表中
- 列表中的每个section必须使用名为"name"首个属性的名字,值必须是文件的相对路径,或者有效的外部资源URL。
- 假如sections列表
列表中,有多个属性指向同一个文件实例,那么这些属性会被合并。
- 假如某一属性在多个列表出现,只有最后一个会被识别使用。
- 不能识别的属性会被忽略
- 所有的属性需要包括一个应用使用的实现规范信息
Manifest文件内容规范
manifest文件: 主section
+ 换行符
+ 0..个独立section
主section
: 版本信息
+ 换行符
+ 0..个主属性
版本信息
: "Manifest-Version:" + 版本号码
版本号码
: 数字
+ 0..个.数字
,即 “1“、”1.0“、”1.0.0“
主属性
: 任意合法的主属性 + 换行符
独立section
: "Name:" + 值
+ 换行符
+ 0..个单独实例属性
单独实例属性
: 任意合法的主属性 + 换行符
换行符
: 可使用:回车换行
'\r\n' 或 换行
'\n' 或 回车
'\r'(但后面不能是换行符)
数字
: {0-9}
上述的规范格式:
- 主属性会被
主section
引用,单独实例属性
会在独立section
引用。 - 某一属性可以同时在
主section
和独立section
中出现,但后者会覆盖主section
的属性值。
下面分别说明两种类型的属性。
主属性
主属性是属于主section
的内容,它们有以下的分组划分:
-
通用属性
- 'Manifest-Version':
- 'Created-By':
- 'Signature-Version':
- 'Class-Path':
-
独立应用的属性
- 'Main-Class':
-
Java小部件的属性(已过期):'Extension-List':(略)"'extension'-Extension-Name":(略)"'extension'-Specification-Version":(略)"'extension'-Implementation-Name":(略)"'extension'-Implementation-Vendor-Id":(略)"'extension'-Implementation-URL":(略)
-
扩展包标识的属性
- 'Extension-Name':
-
扩展包版本信息和封装信息的属性
- 'Implementation-Title':
- 'Implementation-Version':
- 'Implementation-Vendor':
'Implementation-Vendor-Id'(已过期):(略)'Implementation-URL'(已过期):(略)- 'Specification-Title':
- 'Specification-Vendor':
- 'Sealed':
网友评论