apk2

package
v0.0.0-...-529de6a Latest Latest
Warning

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

Go to latest
Published: Apr 15, 2024 License: MPL-2.0 Imports: 13 Imported by: 1

README

APK Signing

APK is Android's application packaging format. It's basically a ZIP file that follows the JAR Signing specification, and stores a manifest of all file checksums that gets signed by a private RSA key.

Android also supports v2 Signing and v3 Signing (set mode: v3enabled) that put signatures in the metadata of the zip file.

Configuration

To generate a key and certificate using the standard keytool approach, use the following command:

keytool -keystore testkeystore.jks -genkey -alias testapp -keysize 2048 -keyalg RSA -validity 10000 -keypass password1 -storepass password1

This will create a file called testkeystore.jks that contains both the private RSA key and the public certificate. To export these in PEM format and load them into the Autograph configuration, we first need to export the keystore into PKCS12, then extract the private key from the PKCS12 file, as follows:

# export the keystore into pkcs12
keytool -importkeystore -srckeystore testkeystore.jks -destkeystore testkeystore.p12 -deststoretype PKCS12 -srcalias testapp -deststorepass password1 -destkeypass password1

# export the private key from the pkcs12 file into PEM
openssl pkcs12 -in testkeystore.p12  -nodes -nocerts -out key.pem

# export the public certificate from the keystore into PEM
keytool -exportcert -keystore testkeystore.jks -alias testapp|openssl x509 -inform der -text

You can then place the certificate and private key in `autograph.yaml`:

signers:
- id: some-android-app
  type: apk2
  mode: v3enabled
  certificate: |
      -----BEGIN CERTIFICATE-----
      MIIH0zCCBbugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBvDELMAkGA1UEBhMCVVMx
      ...
      -----END CERTIFICATE-----
  privatekey: |
      -----BEGIN PRIVATE KEY-----
      MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDHV+bKFLr1p5FR
      ...
      -----END PRIVATE KEY-----

Set the optional mode field to v3enabled to enable APK v3 signatures (in addition to v1 and v2).

Signature request

This signer only supports the /sign/file endpoint.

The /sign/file endpoint takes a whole APK encoded in base64 and no options. It shells out to apksigner to issue v1 JAR signatures and v2 zip file metadata signatures and returns a zip-aligned APK:

[
    {
        "input": "Y2FyaWJvdW1hdXJpY2UK",
        "keyid": "some-android-app",
    }
]

Per the zipalign docs callers should align their APK before signing and verify alignment after signing:

zipalign -v <alignment> infile outfile

# ... call /sign/file

zipalign -v <alignment> signedfile

Signature response

Data Signing

The response to a file signing request contains the base64 of the signed and aligned APK in the signed_file field of the json response. You should base64 decode that field and write the output as a file.

[
  {
    "ref": "7khgpu4gcfdv30w8joqxjy1cc",
    "type": "apk",
    "signer_id": "testapp-android",
    "signed_file": "MIIGPQYJKoZIhvcN..."
  }
]

Verifying signatures

The android SDK has a tool called apksigner that can verify both signature versions, as well as the zip alignment. Note that you need to pass the min-sdk-version to verify the v1 signature.

$ /opt/android-sdk/build-tools/27.0.3/apksigner verify -v --min-sdk-version 23 test.apk
Verifies
Verified using v1 scheme (JAR signing): true
Verified using v2 scheme (APK Signature Scheme v2): true
Number of signers: 1

Documentation

Index

Constants

View Source
const (
	// Type of this signer is "apk2" represents a signer that
	// shells out to apksigner to sign artifacts
	Type = "apk2"

	// ModeV3Enabled enables APK v3 signing
	ModeV3Enabled = "v3enabled"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type APK2Signer

type APK2Signer struct {
	signer.Configuration
	// contains filtered or unexported fields
}

APK2Signer holds the configuration of the signer

func New

func New(conf signer.Configuration) (s *APK2Signer, err error)

New initializes an apk signer using a configuration

func (*APK2Signer) Config

func (s *APK2Signer) Config() signer.Configuration

Config returns the configuration of the current signer

func (*APK2Signer) GetDefaultOptions

func (s *APK2Signer) GetDefaultOptions() interface{}

GetDefaultOptions returns default options of the signer

func (*APK2Signer) GetTestFile

func (s *APK2Signer) GetTestFile() []byte

GetTestFile returns a valid test APK

func (*APK2Signer) SignFile

func (s *APK2Signer) SignFile(file []byte, options interface{}) (signer.SignedFile, error)

SignFile signs a whole aligned APK file with v1 and v2 signatures

type Options

type Options struct {
}

Options are not implemented for this signer

type Signature

type Signature struct {
	Data     []byte
	Finished bool
	// contains filtered or unexported fields
}

Signature is a PKCS7 detached signature

func Unmarshal

func Unmarshal(signature string, content []byte) (sig *Signature, err error)

Unmarshal takes the base64 representation of a v1 JAR PKCS7 detached signature and the content of the signed data, and returns a PKCS7 struct

func (*Signature) Marshal

func (sig *Signature) Marshal() (string, error)

Marshal returns the base64 representation of a v1 JAR signature

func (*Signature) String

func (sig *Signature) String() string

String returns a PEM encoded PKCS7 block

func (*Signature) Verify

func (sig *Signature) Verify() error

Verify verifies an apk pkcs7 signature

WARNING: this function does not verify the JAR manifests or signature formats other than v1 JAR signing

Jump to

Keyboard shortcuts

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