Documentation ¶
Index ¶
- type Attribute
- type Digest
- type Digester
- type Signature
- type SignedData
- type Signer
- type SigningVersion
- type V1Reader
- type V1Writer
- type V2Block
- type Zip
- func (z *Zip) Bytes() []byte
- func (z *Zip) InjectBeforeCD(data []byte) []byte
- func (z *Zip) Sign(keys []*android.SigningCert) (*Zip, error)
- func (z *Zip) SignV1(keys []*android.SigningCert) (*Zip, error)
- func (z *Zip) SignV2(keys []*android.SigningCert) (*Zip, error)
- func (z *Zip) Verify() error
- func (z *Zip) VerifyV1() error
- func (z *Zip) VerifyV2() error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Digester ¶
Digester is a crypto.Hash implementation that implements the Merkel-tree-flavored hash scheme defined in the Android APK v2 signing scheme.
func NewDigester ¶
NewDigester returns a new instance using the provided crypto.Hash algorithm for its underlying hash scheme.
func (*Digester) BlockSize ¶
BlockSize() returns the block size of the Digester, which is the same as the block size of its current underlying crypto.Hash.
func (*Digester) Reset ¶
func (d *Digester) Reset()
Reset clears this Digester, preparing it for a new usage.
func (*Digester) Size ¶
Size() returns the size of the Digester, which is the same as the size of its current underlying crypto.Hash.
func (*Digester) Sum ¶
Sum waits winds up the parallel chunk hashes into the accumulated top-level hash, per Android spec.
func (*Digester) Write ¶
Write starts a parallelized chunk-based hash computation of the input. Note that this differs slightly from a typical crypto.Hash in that the input is, per Android spec, computed in 1k chunks of its input. This means that `d.Write(a); d.Write(b)` != `d.Write(append(a, b...))` unless `a` happens to be an exact multiple of 1k.
This function starts `len(p) / 1k` goroutines.
type Signature ¶
func ParseSignature ¶
type SignedData ¶
type SignedData struct { Digests []*Digest Certs []*x509.Certificate Attributes []*Attribute Raw []byte // used to store raw bytes for signing & verifying }
func ParseSignedData ¶
func ParseSignedData(sd []byte) (*SignedData, error)
func (*SignedData) Marshal ¶
func (sd *SignedData) Marshal() []byte
type Signer ¶
type Signer struct { SignedData *SignedData Signatures []*Signature PublicKey []byte }
func ParseSigner ¶
type SigningVersion ¶
type SigningVersion int
SigningVersion is an enum of all supported Android APK signing scheme versions. Currently these are v1 and v2.
const ( APKSignUnknown SigningVersion = iota APKSignV1 APKSignV2 )
func (SigningVersion) String ¶
func (sv SigningVersion) String() string
type V1Reader ¶
type V1Reader struct {
// contains filtered or unexported fields
}
V1Reader loads an input Zip file and can verify its Android APK v1 signatures (i.e. Java JAR file signatures.)
func ParseZip ¶
ParseZip loads the indicated bytes into a V1Reader, and parses out the JAR manifest and related signature files. While doing so, it must necessarily stream through the file's contents. ParseZip returns a non-nil error if the bytes fail to parse as a Zip, or if it is missing the required manifest file or signing files.
If `writer` is not nil, each file will be passed through to it while the Zip's contents are being iterated. This allows the caller to construct a V1Writer from the input without having to make a second pass over the Zip contents. That is, if you only want to load and verify a Zip's signature, pass a nil `writer`; but if you are intending to sign the Zip, pass in a `writer`.
Note that unlike the V2 handling code in v2sign.go in this package, this function does use the standard Go zip library.
type V1Writer ¶
type V1Writer struct {
// contains filtered or unexported fields
}
V1Writer is used to construct a Zip file and sign its contents.
func NewV1Writer ¶
func NewV1Writer() *V1Writer
func (*V1Writer) Add ¶
Add adds the specified zip.File to the new Zip being created by this `v1`. All file metadata is also copied, except for CRC32 and size headers; these are recomputed.
func (*V1Writer) Sign ¶
func (v1 *V1Writer) Sign(keys []*android.SigningCert, signifyV2 bool) error
Sign generates the JAR manifest and assorted signature files that constitute a JAR signature. That is, it generates the manifest and `.SF` files with the digests of the JAR's files, and then signs the `.SF` file. All these files are then included in the Zip itself.
type V2Block ¶
type V2Block struct {
Signers []*Signer
}
V2Block is a logical representation of the Android v2 signing scheme block. It can marshal to or unmarshal from a []byte.
func ParseV2Block ¶
ParseV2Block parses its input as an Android v2 signing scheme block. It returns a non-nil error if the input does not follow that specification.
type Zip ¶
type Zip struct { IsAPK bool IsV1Signed bool IsV2Signed bool // contains filtered or unexported fields }
Zip loads and performs operations on ZIP files required for signing Android APKs. It supports the "Android Signing Scheme v2" introduced in Nougat.
See https://source.android.com/security/apksigning/v2.html
As this signing scheme does not rely on any Android-related content in the Zip file itself, it can actually be used to sign arbitrary Zip files; they need not be Android APKs.
func NewZip ¶
NewZip attempts to parse its input as a Zip file, determining along the way whether the input is actually an Android APK, and whether it is signed with either the v1 or v2 signing schemes. A non-nil error is returned if the input does not parse as a Zip. The IsAPK, IsV1Signed, and IsV2Signed will be populated once this function returns a nil error; until they, their values are untrustworthy.
Note that this function does NOT use the Go standard zip library. As the Android v2 signing scheme is non-standard and involves injecting a non-Zip data-block into the file before the Zip central directory, this code does byte parsing of its input to locate the relevant offsets.
func (*Zip) InjectBeforeCD ¶
InjectBeforeCD modifies the Zip file bytes represented by this instance by injecting the input bytes into the file immediately before the Zip Central Directory block. The End of Central Directory block's record of the Central Directory offset is updated accordingly, so that the new Zip file is valid. Note that this is the behavior specified by the Android APK signing scheme v2, which is what this function is intended to be used for.
The returned slice is backed by a new array. The bytes represented by `z` are not modified, nor is any other state of `z`. If the resulting Zip bytes need to be interacted with, they must be parsed into a new Zip instance.
func (*Zip) Sign ¶
func (z *Zip) Sign(keys []*android.SigningCert) (*Zip, error)
Sign signs the zip with the provided keys, using BOTH the v1 (JAR signer) and v2 (Android-specific whole-file) signing rubrics. Note that `Sign()` IS NOT equivalent to `SignV1(); SignV2()`. When signed with both schemes, the JAR `.SF` files have an additional header, per spec.
func (*Zip) SignV1 ¶
func (z *Zip) SignV1(keys []*android.SigningCert) (*Zip, error)
SignV1 signs the zip with the provided keys, using the Java signed-JAR signing rubric, only. This was used by Android up to the Nougat release, when it was supplemented by a more secure whole-file "v2" scheme.
func (*Zip) SignV2 ¶
func (z *Zip) SignV2(keys []*android.SigningCert) (*Zip, error)
SignV2 signs the zip with the provided keys, using the Android-specific whole-file "v2" signing rubric, only.
func (*Zip) Verify ¶
Verify returns a non-nil error if the represented Zip file has a signature (under either v1 or v2 rubric) that does not validate. Note that calling this when both z.IsV1Signed == false and z.IsV2Signed == false is always an error. Verify returns nil if the signature(s) validate(s).
func (*Zip) VerifyV1 ¶
VerifyV1 returns a non-nil error if the represented Zip file has a v1 (i.e. Java signed JAR) signature that does not verify. Note that calling this when z.IsV1Signed == false is always an error. VerifyV1 returns nil if the signature validates.