apksign

package
v0.0.0-...-d774415 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 12, 2023 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Attribute

type Attribute struct {
	ID    uint32
	Value []byte
}

func (*Attribute) Marshal

func (a *Attribute) Marshal() []byte

type Digest

type Digest struct {
	AlgorithmID uint32
	Digest      []byte
}

* Struct hierarchy corresponding to the byte structure specified in the URL above.

func (*Digest) Marshal

func (d *Digest) Marshal() []byte

type Digester

type Digester struct {
	Hash crypto.Hash
	// contains filtered or unexported fields
}

Digester is a crypto.Hash implementation that implements the Merkel-tree-flavored hash scheme defined in the Android APK v2 signing scheme.

func NewDigester

func NewDigester(h crypto.Hash) *Digester

NewDigester returns a new instance using the provided crypto.Hash algorithm for its underlying hash scheme.

func (*Digester) BlockSize

func (d *Digester) BlockSize() int

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

func (d *Digester) Size() int

Size() returns the size of the Digester, which is the same as the size of its current underlying crypto.Hash.

func (*Digester) Sum

func (d *Digester) Sum(b []byte) []byte

Sum waits winds up the parallel chunk hashes into the accumulated top-level hash, per Android spec.

func (*Digester) Write

func (d *Digester) Write(p []byte) (n int, err error)

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

type Signature struct {
	AlgorithmID uint32
	Signature   []byte
}

func ParseSignature

func ParseSignature(sigs []byte) ([]*Signature, error)

func (*Signature) Marshal

func (s *Signature) Marshal() []byte

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

func ParseSigner(signer []byte) (*Signer, error)

func (*Signer) Marshal

func (s *Signer) Marshal() []byte

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

func ParseZip(buf []byte, writer *V1Writer) (*V1Reader, error)

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.

func (*V1Reader) GetOnlySigner

func (v1 *V1Reader) GetOnlySigner() *x509.Certificate

func (*V1Reader) Verify

func (v1 *V1Reader) Verify() error

Verify returns a non-nil error if the `v1` JAR/APK fails to verify under the standard JAR signing scheme. It returns nil if the file's signatures all verify.

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

func (v1 *V1Writer) Add(zf *zip.File) error

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) Marshal

func (v1 *V1Writer) Marshal() ([]byte, error)

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

func ParseV2Block(block []byte) (*V2Block, error)

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.

func (*V2Block) Sign

func (v2 *V2Block) Sign(z *Zip, keys []*android.SigningCert) ([]byte, error)

Sign generates an Android v2 signature block from `v2` and then injects that block into the indicated Zip instance. On success, it returns the bytes of the resulting signed Zip file, and a nil error. On failure, it returns a non-nil error.

func (*V2Block) Verify

func (v2 *V2Block) Verify(z *Zip) error

Verify returns a non-nil error if the Android APK v2 signing scheme represented by `v2` fails to validate, per the spec.

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

func NewZip(buf []byte) (*Zip, error)

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) Bytes

func (z *Zip) Bytes() []byte

Bytes returns a slice over a new copy of the bytes underlying `z`.

func (*Zip) InjectBeforeCD

func (z *Zip) InjectBeforeCD(data []byte) []byte

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

func (z *Zip) Verify() error

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

func (z *Zip) VerifyV1() error

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.

func (*Zip) VerifyV2

func (z *Zip) VerifyV2() error

VerifyV2 returns a non-nil error if the represented Zip file has a v2 (i.e. Android-specific whole-file) signature that does not verify. Note that calling this when z.IsV2Signed == false is always an error. VerifyV2 returns nil if the signature validates.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL