it's my first time using bitbucket pipelines, I want to build an signed apk, I have the script, it generates the apk already, however, it seems there is something wrong on the signature, I've been trying to figure out why but I have had any success.
As you see on the script above, I'm generating the apk, I've created some repository variables to pass the signature data, so once the apk is ready, I use the following command to verify the apk signature :
keytool -printcert -jarfile app-debug.apk
then I see the signature data does not match with the apk signed by the ide (using the same certificate,jks, passwords and alias)
I hope any of you can help me, thanks.
I had a similar issue, be sure you are correctly encoding/decoding your .jks file...
encode:
base64 -w 0 my_keystore_file_name.jks > envout.txt
copy the contents of envout.txt to $DEBUG_STORE_FILE_BASE64 repository variable. Meaning you open envout.txt (in notepad or something) select all ctrl+a and copy ctrl+c
decode:
echo $DEBUG_STORE_FILE_BASE64 | base64 -d > my_keystore_file_name.jks
it may not matter, but $DEBUG_STORE_FILE should just be filename, and if you still have issues you could try to not use a secured repository variable, or move the file after its created:
mv $DEBUG_STORE_FILE keys/$DEBUG_STORE_FILE
or
cp $DEBUG_STORE_FILE keys/$DEBUG_STORE_FILE
Related
In Huawei App Gallery I have to update an existing aab application. Site redirects me to App signing page and there are steps that I have to follow in order to sign the app successfully. These are the steps provided:
Obtain the pepk.jar file from the Internet or another legitimate source.
Export and encrypt your private key and public key certificate into a ZIP file. Parameters in bold must be replaced as needed. Then, enter your data storage location and key password as prompted.
java -jar pepk.jar --keystore test.jks --alias test --output=output.zip --encryptionkey=<some_encryption_key> --include-cert
Upload the ZIP file containing the private key and public key certificate. (The ZIP file contains only certificate.pem and encryptedPrivateKey.)
Now I have 2 problems.
First one is, when I run the code in 2nd step in CMD. I get include-cert flag is not provided error. However when I write --include-cert=certificate.pem or --include-cert certificate.pem it says flag is unrecognized.
Second one is, I put certificate.pem and private key to folder and then turn it into ZIP. But when I click on submit it gives me Make sure the package contains only the certificate.pem and encryptedPrivateKey files error. Is not encryptedPrivateKey is the file that is exported by AndroidStudio when you generate an app bundle or Apk into the same location with .pepk extension?
I don't know what am I missing in order to sign my application. Any help would be appreciated, thanks in advance
If "No value provided for flag: include-cert" is displayed, the pepk.jar file is incorrect. You need to replace it with a correct one.
https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agc-appsigning-faq-0000001052944432
I get include-cert flag is not provided error. However when I write --include-cert=certificate.pem or --include-cert certificate.pem it says flag is unrecognized.
It is recommended that you do not change the command and follow the commands in the document.
You could click here to try out.
And this is the App Signing Operation Guide video for reference.
Dear stackoverflow community, once more I turn to you :)
I've recently come across the wonder of Gitlab and their very nice bundled CI/CD solution. It works gallantly however, we all need to sign our binaries don't we and I've found no way to upload a key as I would to a Jenkins server for doing this.
So, how can I, without checking in my keys and secrets sign my android (actually flutter) application when building a release?
From what I see, most people define the build job with signing settings referring to a non-committed key.properties file specifying a local keystore.jks. This works fine when building APKs locally but if I would like to build and archive them as a part of the CI/CD job, how do I?
For secret keys, for example the passwords to the keystore itself, I've found that I can simply store them as protected variables but the actual keystore file itself. What can I do about that?
Any ideas, suggestions are dearly welcome.
Cheers
Edit:
I apologise for never marking a right answer here and as #IvanP proposed the solution of writing individual values to a file was what I used for a long time. But as #VonC added later, Gitlab now has the capability to data as actual files which simplifies this so I am marking that as the correct answer.
Usually I store keystore file (as base64 string), alias and passwords to Gitlab's secrets variables.
In the .gitlab-ci.yml do something like:
create_property_files:
stage: prepare
only:
- master
script:
- echo $KEYSTORE | base64 -d > my.keystore
- echo "keystorePath=my.keystore" > signing.properties
- echo "keystorePassword=$KEYSTORE_PASSWORD" >> signing.properties
- echo "keyAlias=$ALIAS" >> signing.properties
- echo "keyPassword=$KEY_PASSWORD" >> signing.properties
artifacts:
paths:
- my.keystore
- signing.properties
expire_in: 10 mins
And, finally, in your build gradle:
signingConfigs {
release {
file("../signing.properties").with { propFile ->
if (propFile.canRead()) {
def properties = new Properties()
properties.load(new FileInputStream(propFile))
storeFile file(properties['keystorePath'])
storePassword properties['keystorePassword']
keyAlias properties['keyAlias']
keyPassword properties['keyPassword']
} else {
println 'Unable to read signing.properties'
}
}
}
}
From IvanP's answer:
Usually I store keystore file (as base64 string), alias and passwords to Gitlab's secrets variables.
That should be easier with GitLab 15.0 (May 2022)
Project-level Secure Files in open beta
Previously, it was difficult to use binary files in your CI/CD pipelines because CI/CD variables could only contain text values. This made it difficult to make use of profiles, certificates, keystores, and other secure information, which are important for teams building mobile apps.
Today we are releasing Project-level Secure Files in open beta. Now you can upload binary files to projects in GitLab, and include those files in CI/CD jobs to be used in the build and release processes as needed. Secure Files are stored outside of version control and are not part of the project repository.
Please leave us your feedback about your experience with this feature in the feedback issue.
See Documentation and Issue.
Thanks to #IvanP's answer but I had to make some changes in the Gitlab pipeline to get it working correctly.
Export the Keystore as a base64 string:
openssl base64 -A -in my.keystore > base64
Create a new variable and copy-paste the value in the file base64. Be careful while doing this, I screwed up the formatting and the pipeline was not able to decode the Keystore. The variables had to be referred to with ${} rather than just $.
- echo -n ${ANDROID_KEYSTORE} | base64 -d > my.keystore
- echo "keystorePath=../my.keystore" > myapp.properties
- echo "keystorePassword=${KEYSTORE_PASSWORD}" >> myapp.properties
- echo "keyAlias=${ALIAS_NAME}" >> myapp.properties
- echo "keyPassword=${KEY_PASSWORD}" >> myapp.properties
Refer to the myapp.properties in your build.gradle as explained above in the #IvanP's answer.
I've used git-secret in the past to check-in password protected secret files. Then pass the password via a secret/protected environmental variable (as you already know) and modify the .gitlab-ci.yml to use the password to open the files and use them.
Another solution is to use android.injected properties:
First encode the certificate file:
openssl enc -base64 -in certFile -out certFileEncoded
Get the content of certFileEncoded file and define in the Gitlab settings as a file type variable.
Inject certificate, alias and password in the assemble task:
script:
- openssl enc -d -base64 -in $CERT_FILE_BASE_64 -out certFile
- ./gradlew :app:assembleRelease -Pandroid.injected.signing.store.file=$(pwd)/certFile -Pandroid.injected.signing.store.password=$CERT_PASS -Pandroid.injected.signing.key.alias=$CERT_ALIAS -Pandroid.injected.signing.key.password=$CERT_PASS
Here the CERT_ALIAS and CERT_PASS are masked variables.
I have Qt application to deploy on Android. I am using command line build to generate an apk signed with my .keystore file. I am well able to do it using following command where I am using androiddeployqt.
androiddeployqt --sign my_key.keystore myAlias --storepass my_password --output android --verbose --input my_app.so-deployment-settings.json
Above command works great from my shell script to generate a signed apk. But I want to avoid writing my password on the command as done above. Typing androiddeployqt -help shows that there is a --sigfile <file>: Name of .SF/.DSA file option that I can use. But I don't know how to create this sigfile of extension .SF/.DSA.
Can someone please suggest how to create a sigfile of extension .SF/.DSA which I can use with androiddeployqt command with --sigfile as option ? Am I correct in understanding that I need a file of extension .SF or .DSA ?
Or, is there some other way I can hide my password from showing up on the script's code ?
Okay, I had to look at the oracle docs..as long as you have a keystore cert you supply the sigfile names it it creates those files for you per:
https://docs.oracle.com/javase/tutorial/deployment/jar/signing.html
and the qt tool you are using plugins into that so you should be good to go
I currently use Travis CI for my open source project. All went well till I tried to upload an artifact to Maven Central staging repository once the travis build was successful.
Please find the steps i followed below:
Added a initiate-publish.sh script file which will publish to Maven central after build is successful.
Encrypted the following
Encryption password to secure my secring file -> travis encrypt -r username/gitrepo ENCRYPT_PASSWORD="my password"
secring.gpg file - openssl aes-256-cbc -in .utility/local.secring.gpg -out .utility/secring.gpg.enc -pass pass:"my password"
-> This generated secring.gpg.enc which i added to my repository
Modfied .travis.yml file with the following
before_install:
openssl aes-256-cbc -pass pass:$ENCRYPTION_PASSWORD -in .utility/secring.gpg.enc -out .utility/local.secring.gpg -d
I committed the files to Git which triggered a build.
The after_success: exits with an error stating
"Could not evaluate onlyIf predicate for task ':android-db-migration-library:signArchives'.
Unable to retrieve secret key from key ring file '/home/travis/build/PalomaMobile/android-db-migration/android-db-migration-library/.utility/local.secring.gpg' as it does not exist"
You can view the logs https://travis-ci.org/PalomaMobile/android-db-migration/builds/63114335
From what i understand, the "before install" will decrypt the file and store it and my release script can access it.
Could you please help me understand why this happens. You can view my .travis.yml file, release script file etc.. # https://github.com/PalomaMobile/android-db-migration
I double-checked your build log and it seems that your signArchive task is expecting the secret key to be located in
/home/travis/build/PalomaMobile/android-db-migration/android-db-migration-library/.utility/generated.secring.gpg
but in fact it is located in
/home/travis/build/PalomaMobile/android-db-migration/.utility/generated.secring.gpg
So I would suggest using an absolute path to the key file instead of a relative one in your .utility/initiate-publish.sh file.
Hope this helps!
I need to be able to build the release version of my apk, using a Jenkins job.
From reading the following SO question
How to create a release signed apk file using Gradle?
I understand I can do it in one of two ways. Either get the user to enter the password at cmd prompt, or store my password details in a plain text file that doesn't get committed to git, and lives on my local machine.
Neither of these will work when running the build job on jenkins though. 1) I can't gain user input because this may be running in the middle of the night (I don't even know how to get user input from the cmd line even if the user was at their machine) 2) Anyone who can gain access to that build box, would be able to cat the contents of that file either via the cmd line or from another build.gradle job running on that jenkins server.
Does anyone know of anyway I can keep my password hidden but so that the Jenkins job can access it?
Thanks
You can use Mask Password Plugin, which does just that. Or the same functionality is included in EnvInject plugin, and sooner or later all Jenkins projects get a need for EnvInject plugin (that does many other things), so might as well start using it now.
To securely use a password from within a build/post-build step
Install EnvInject plugin.
Under Jenkins Global Configuration, find Global Passwords section.
Add a name (this will be the environment variable name) and password (will be starred **** ).
Under Job Configuration, find Build Environment section.
Checkmark Inject passwords to the build as environment variables.
Then checkmark Global passwords.
In any build step, you can now use $name (as defined earlier) to refer to a password as you would if you were typing it in plain text.
The password variable is injected only at job execution time (typing $name on command line of the server by itself will not produce anything, and like all Jenkins variables, it is not persistent).
The job console log will show **** instead of password, if it appears.
You could configure passwords per job, rather than globally, so that other jobs can't use it.
The only security concern is that if someone has administrative permissions to configure your job, they can write echo $name > secretpassword.txt into a build step, and then review the file in the workspace. But you should be careful who you assign administrative rights to.
You should take a look for this plugin
https://wiki.jenkins-ci.org/display/JENKINS/Mask+Passwords+Plugin
If your Jenkins instance happens to be running on EC2, and you don't want to permanently store secrets in the file system, you can put the store and key passwords into Systems Manager Parameter Store, then query them at build time. In addition, you can put the keystore itself into external storage, such as S3, and only keep it locally for the duration of the build.
Here is a sample build script (assume that the secret parameters are named android-keystore-pass and android-signature-key-pass):
set -o errexit
set -o pipefail
keystore_file=keystore.properties
keystore=wise.jks
aws s3 cp s3://path-to-android/$keystore .
chmod go-rwx $keystore
touch $keystore_file
chmod go-rwx $keystore_file
cat > $keystore_file << EOF
storePassword=`aws ssm get-parameters --names android-keystore-pass --with-decryption | cut -f4`
keyPassword=`aws ssm get-parameters --names android-signature-key-pass --with-decryption | cut -f4`
keyAlias=android
storeFile=$WORKSPACE/$keystore
EOF
An example of the Gradle build scripts can be found in this answer. You can commit a dummy keystore.properties to source control so that (non-release) builds work on dev machines.
There are also open-source secret distribution tools that are platform-independent, e.g. Vault, but I haven't tried any of them.