gplay-signing-setup

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Android App Signing Setup

Android应用签名设置

Use this skill when you need to set up or manage app signing for Google Play.
当你需要为Google Play设置或管理应用签名时,可以使用本指南。

Understanding Android App Signing

了解Android应用签名

Android apps must be signed with a certificate before upload. Two signing approaches:
  1. App Signing by Google Play (Recommended) - Google manages your signing key
  2. Manual Signing (Legacy) - You manage your signing key
Android应用在上传前必须使用证书签名。有两种签名方式:
  1. App Signing by Google Play(推荐)- 由Google管理你的签名密钥
  2. 手动签名(传统方式)- 由你自行管理签名密钥

Create a New Keystore

创建新的密钥库

Generate keystore

生成密钥库

bash
keytool -genkey -v \
  -keystore release.keystore \
  -alias my-app-key \
  -keyalg RSA \
  -keysize 2048 \
  -validity 10000
You'll be prompted for:
  • Keystore password (store securely!)
  • Key password (can be same as keystore password)
  • Your name/organization details
bash
keytool -genkey -v \
  -keystore release.keystore \
  -alias my-app-key \
  -keyalg RSA \
  -keysize 2048 \
  -validity 10000
你将被要求输入:
  • 密钥库密码(请安全存储!)
  • 密钥密码(可与密钥库密码相同)
  • 你的姓名/组织信息

Keystore file location

密钥库文件存储位置

  • Development: Keep locally, never commit to git
  • Production: Store in secure location (password manager, secrets vault)
  • CI/CD: Use encrypted secrets
  • 开发环境:本地保存,绝对不要提交至git
  • 生产环境:存储在安全位置(密码管理器、密钥保险箱)
  • CI/CD环境:使用加密的密钥

Configure Gradle Signing

配置Gradle签名

gradle.properties (gitignored)

gradle.properties(需加入git忽略)

properties
KEYSTORE_FILE=/path/to/release.keystore
KEYSTORE_PASSWORD=your_keystore_password
KEY_ALIAS=my-app-key
KEY_PASSWORD=your_key_password
properties
KEYSTORE_FILE=/path/to/release.keystore
KEYSTORE_PASSWORD=your_keystore_password
KEY_ALIAS=my-app-key
KEY_PASSWORD=your_key_password

app/build.gradle

app/build.gradle

groovy
android {
    signingConfigs {
        release {
            storeFile file(project.property('KEYSTORE_FILE'))
            storePassword project.property('KEYSTORE_PASSWORD')
            keyAlias project.property('KEY_ALIAS')
            keyPassword project.property('KEY_PASSWORD')
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}
groovy
android {
    signingConfigs {
        release {
            storeFile file(project.property('KEYSTORE_FILE'))
            storePassword project.property('KEYSTORE_PASSWORD')
            keyAlias project.property('KEY_ALIAS')
            keyPassword project.property('KEY_PASSWORD')
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

Using environment variables (CI/CD)

使用环境变量(CI/CD场景)

groovy
android {
    signingConfigs {
        release {
            storeFile file(System.getenv("KEYSTORE_FILE") ?: "release.keystore")
            storePassword System.getenv("KEYSTORE_PASSWORD")
            keyAlias System.getenv("KEY_ALIAS")
            keyPassword System.getenv("KEY_PASSWORD")
        }
    }
}
groovy
android {
    signingConfigs {
        release {
            storeFile file(System.getenv("KEYSTORE_FILE") ?: "release.keystore")
            storePassword System.getenv("KEYSTORE_PASSWORD")
            keyAlias System.getenv("KEY_ALIAS")
            keyPassword System.getenv("KEY_PASSWORD")
        }
    }
}

Play App Signing Setup

Play App Signing设置

Enable Play App Signing (New App)

启用Play App Signing(新应用)

  1. Build and sign AAB with upload key:
    bash
    ./gradlew bundleRelease
  2. Upload AAB to Play Console:
    bash
    gplay release \
      --package com.example.app \
      --track internal \
      --bundle app-release.aab
  3. Google Play generates app signing key automatically
  4. Download upload certificate:
    • Go to Play Console → App → Setup → App signing
    • Download "Upload certificate" (will be used for future uploads)
  1. 使用上传密钥构建并签名AAB
    bash
    ./gradlew bundleRelease
  2. 将AAB上传至Play Console
    bash
    gplay release \
      --package com.example.app \
      --track internal \
      --bundle app-release.aab
  3. Google Play自动生成应用签名密钥
  4. 下载上传证书
    • 进入Play Console → 应用 → 设置 → 应用签名
    • 下载「上传证书」(将用于后续上传)

Migrate Existing App to Play App Signing

将现有应用迁移至Play App Signing

If your app uses manual signing:
  1. Export upload key:
    bash
    keytool -export -rfc \
      -keystore release.keystore \
      -alias my-app-key \
      -file upload_cert.pem
  2. Encrypt private key (required by Google):
    bash
    # Generate password for encryption
    openssl rand -base64 32 > encryption_password.txt
    
    # Export and encrypt private key
    keytool -importkeystore \
      -srckeystore release.keystore \
      -destkeystore encrypted.p12 \
      -deststoretype PKCS12 \
      -srcalias my-app-key \
      -deststorepass $(cat encryption_password.txt)
  3. Upload to Play Console:
    • Go to Play Console → App → Setup → App signing
    • Choose "Export and upload a key"
    • Upload encrypted.p12 and encryption_password.txt
  4. Download new upload key:
    • After migration, download new upload certificate
    • Use this for all future uploads
如果你的应用使用手动签名:
  1. 导出上传密钥
    bash
    keytool -export -rfc \
      -keystore release.keystore \
      -alias my-app-key \
      -file upload_cert.pem
  2. 加密私钥(Google要求):
    bash
    # 生成加密密码
    openssl rand -base64 32 > encryption_password.txt
    
    # 导出并加密私钥
    keytool -importkeystore \
      -srckeystore release.keystore \
      -destkeystore encrypted.p12 \
      -deststoretype PKCS12 \
      -srcalias my-app-key \
      -deststorepass $(cat encryption_password.txt)
  3. 上传至Play Console
    • 进入Play Console → 应用 → 设置 → 应用签名
    • 选择「导出并上传密钥」
    • 上传encrypted.p12和encryption_password.txt
  4. 下载新的上传密钥
    • 迁移完成后,下载新的上传证书
    • 后续所有上传都需使用此证书

Verify Keystore

验证密钥库

List keys in keystore

列出密钥库中的密钥

bash
keytool -list -v -keystore release.keystore
bash
keytool -list -v -keystore release.keystore

Check certificate validity

检查证书有效期

bash
keytool -list -v \
  -keystore release.keystore \
  -alias my-app-key \
  | grep Valid
bash
keytool -list -v \
  -keystore release.keystore \
  -alias my-app-key \
  | grep Valid

Extract certificate fingerprint

提取证书指纹

bash
undefined
bash
undefined

SHA-256 (for Firebase, etc.)

SHA-256(用于Firebase等服务)

keytool -list -v
-keystore release.keystore
-alias my-app-key
| grep SHA256
undefined
keytool -list -v
-keystore release.keystore
-alias my-app-key
| grep SHA256
undefined

Verify APK/AAB Signature

验证APK/AAB签名

Check AAB signature

检查AAB签名

bash
jarsigner -verify -verbose -certs app-release.aab
bash
jarsigner -verify -verbose -certs app-release.aab

Check APK signature

检查APK签名

bash
jarsigner -verify -verbose -certs app-release.apk
bash
jarsigner -verify -verbose -certs app-release.apk

CI/CD Signing

CI/CD签名

GitHub Actions Example

GitHub Actions示例

yaml
- name: Decode keystore
  run: |
    echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > release.keystore

- name: Build signed AAB
  env:
    KEYSTORE_FILE: release.keystore
    KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
    KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
    KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
  run: |
    ./gradlew bundleRelease

- name: Clean up keystore
  if: always()
  run: rm -f release.keystore
yaml
- name: Decode keystore
  run: |
    echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > release.keystore

- name: Build signed AAB
  env:
    KEYSTORE_FILE: release.keystore
    KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
    KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
    KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
  run: |
    ./gradlew bundleRelease

- name: Clean up keystore
  if: always()
  run: rm -f release.keystore

Store keystore as base64

将密钥库存储为base64格式

bash
undefined
bash
undefined

Encode keystore to base64

将密钥库编码为base64

base64 -i release.keystore -o keystore_base64.txt
base64 -i release.keystore -o keystore_base64.txt

Add to GitHub Secrets as KEYSTORE_BASE64

添加至GitHub Secrets,命名为KEYSTORE_BASE64

undefined
undefined

Upload Certificate Management

上传证书管理

Register upload certificate for existing app

为现有应用注册新的上传证书

If you lose your upload key:
  1. Generate new keystore (as shown above)
  2. Export certificate:
    bash
    keytool -export -rfc \
      -keystore new-upload.keystore \
      -alias my-app-key \
      -file new_upload_cert.pem
  3. Contact Google Play support to reset upload key:
    • Go to Play Console → Help
    • Request upload certificate reset
    • Provide new_upload_cert.pem
如果你丢失了上传密钥:
  1. 生成新的密钥库(如前文所示)
  2. 导出证书
    bash
    keytool -export -rfc \
      -keystore new-upload.keystore \
      -alias my-app-key \
      -file new_upload_cert.pem
  3. 联系Google Play支持重置上传密钥
    • 进入Play Console → 帮助
    • 申请重置上传证书
    • 提供new_upload_cert.pem

Security Best Practices

安全最佳实践

DO:

建议:

  • ✅ Use strong passwords (16+ characters)
  • ✅ Store keystore in multiple secure locations
  • ✅ Use different keys for different apps
  • ✅ Enable Play App Signing
  • ✅ Keep upload key separate from production
  • ✅ Document key details securely (not passwords!)
  • ✅ Set calendar reminder for key expiration (10-25 years)
  • ✅ 使用强密码(16位以上)
  • ✅ 在多个安全位置备份密钥库
  • ✅ 为不同应用使用不同的密钥
  • ✅ 启用Play App Signing
  • ✅ 将上传密钥与生产环境分离
  • ✅ 安全记录密钥详情(不要记录密码!)
  • ✅ 设置密钥过期提醒(10-25年)

DON'T:

禁止:

  • ❌ Commit keystores to git
  • ❌ Share keystores via email/chat
  • ❌ Use weak or obvious passwords
  • ❌ Store passwords in code
  • ❌ Forget to backup keystores
  • ❌ Use same key for debug and release
  • ❌ 将密钥库提交至git
  • ❌ 通过邮件/聊天分享密钥库
  • ❌ 使用弱密码或易猜测的密码
  • ❌ 在代码中存储密码
  • ❌ 忘记备份密钥库
  • ❌ 为调试版和正式版使用相同密钥

Keystore Backup Strategy

密钥库备份策略

What to backup:

需要备份的内容:

  1. Keystore file (
    release.keystore
    )
  2. Key alias name
  3. Keystore password (in password manager)
  4. Key password (in password manager)
  1. 密钥库文件(
    release.keystore
  2. 密钥别名
  3. 密钥库密码(存储在密码管理器中)
  4. 密钥密码(存储在密码管理器中)

Where to backup:

备份位置:

  • Password manager (1Password, LastPass, etc.)
  • Encrypted cloud storage
  • Company secrets vault
  • Physical secure storage (for enterprise)
  • 密码管理器(1Password、LastPass等)
  • 加密云存储
  • 企业密钥保险箱
  • 物理安全存储(企业场景)

Test restore process:

测试恢复流程:

bash
undefined
bash
undefined

Verify you can use the backup

验证备份是否可用

keytool -list -v -keystore backup/release.keystore
undefined
keytool -list -v -keystore backup/release.keystore
undefined

Troubleshooting

故障排除

"jarsigner: unable to sign jar"

"jarsigner: unable to sign jar"

  • Check keystore password is correct
  • Verify keystore file path
  • Ensure keystore alias exists
  • 检查密钥库密码是否正确
  • 验证密钥库文件路径
  • 确保密钥别名存在

"Failed to read key from keystore"

"Failed to read key from keystore"

  • Key alias might be wrong
  • Key password might be wrong
  • Keystore might be corrupted
  • 密钥别名可能错误
  • 密钥密码可能错误
  • 密钥库可能已损坏

"Upload certificate doesn't match"

"Upload certificate doesn't match"

  • You're using wrong keystore
  • Keystore was regenerated (contact support)
  • Using app signing key instead of upload key
  • 你使用了错误的密钥库
  • 密钥库已重新生成(联系支持)
  • 使用了应用签名密钥而非上传密钥

Lost keystore?

丢失密钥库?

  • If using Play App Signing: Contact Google to reset upload key
  • If not using Play App Signing: Cannot recover, must publish new app
  • 如果已启用Play App Signing:联系Google重置上传密钥
  • 如果未启用Play App Signing:无法恢复,必须发布新应用

Multiple Apps, Multiple Keys

多应用多密钥管理

Organize multiple keystores

整理多个密钥库

~/keystores/
├── app1-release.keystore
├── app2-release.keystore
└── app3-release.keystore
~/keystores/
├── app1-release.keystore
├── app2-release.keystore
└── app3-release.keystore

Use different gradle.properties per app

为每个应用使用独立的gradle.properties

properties
undefined
properties
undefined

app1/gradle.properties

app1/gradle.properties

KEYSTORE_FILE=~/keystores/app1-release.keystore KEY_ALIAS=app1-key
KEYSTORE_FILE=~/keystores/app1-release.keystore KEY_ALIAS=app1-key

app2/gradle.properties

app2/gradle.properties

KEYSTORE_FILE=~/keystores/app2-release.keystore KEY_ALIAS=app2-key
undefined
KEYSTORE_FILE=~/keystores/app2-release.keystore KEY_ALIAS=app2-key
undefined

Key Rotation

密钥轮换

Android apps are typically signed with long-lived keys (10-25 years), but if you need to rotate:
  1. Only possible with Play App Signing enabled
  2. Contact Google Play Support to rotate app signing key
  3. Upload new upload certificate when prompted
  4. All future builds must use new upload key
Android应用通常使用长期密钥(10-25年),但如果需要轮换:
  1. 仅在启用Play App Signing的情况下可行
  2. 联系Google Play支持轮换应用签名密钥
  3. 按提示上传新的上传证书
  4. 所有后续构建必须使用新的上传密钥

Documentation Template

文档模板

Keep this info in your password manager:
App Name: My Awesome App
Package: com.example.app
Keystore File: release.keystore (backed up in Dropbox)
Keystore Password: [IN PASSWORD MANAGER]
Key Alias: my-app-key
Key Password: [IN PASSWORD MANAGER]
Certificate Validity: Valid until 2035-02-05
SHA-256 Fingerprint: AB:CD:EF:12:...
Play App Signing: Enabled
Notes: Upload key only, Google manages app signing key
将以下信息存储在密码管理器中:
应用名称:我的精彩应用
包名:com.example.app
密钥库文件:release.keystore(已备份至Dropbox)
密钥库密码:[存储在密码管理器中]
密钥别名:my-app-key
密钥密码:[存储在密码管理器中]
证书有效期:至2035-02-05
SHA-256指纹:AB:CD:EF:12:...
Play App Signing:已启用
备注:仅使用上传密钥,应用签名密钥由Google管理