1
1
# PHAR signing best practices
2
2
3
3
1 . [ Built-in PHAR API] ( #built-in-phar-api )
4
- 1 . [ How to sign your PHAR] ( #how-to-sign-your-phar )
5
- 1 . [ How it works] ( #how-it-works )
6
- 1 . [ Why it is bad] ( #why-it-is-bad )
4
+ 1 . [ How to sign your PHAR] ( #how-to-sign-your-phar )
5
+ 1 . [ How it works] ( #how-it-works )
6
+ 1 . [ Why it is bad] ( #why-it-is-bad )
7
7
1 . [ How to (properly) sign your PHAR] ( #how-to-properly-sign-your-phar )
8
- 1 . [ Create a new GPG-key] ( #create-a-new-gpg-key )
9
- 1 . [ Manually signing] ( #manually-signing )
10
- 1 . [ Generate the encryption key] ( #generate-the-encryption-key )
11
- 1 . [ Secure your encryption key] ( #secure-your-encryption-key )
12
- 1 . [ Sign your PHAR] ( #sign-your-phar )
13
- 1 . [ Verifying the PHAR signature] ( #verifying-the-phar-signature )
8
+ 1 . [ Create a new GPG-key] ( #create-a-new-gpg-key )
9
+ 1 . [ Manually signing] ( #manually-signing )
10
+ 1 . [ Generate the encryption key] ( #generate-the-encryption-key )
11
+ 1 . [ Secure your encryption key] ( #secure-your-encryption-key )
12
+ 1 . [ Sign your PHAR] ( #sign-your-phar )
13
+ 1 . [ Verifying the PHAR signature] ( #verifying-the-phar-signature )
14
14
1 . [ Automatically sign in GitHub Actions] ( #automatically-sign-in-github-actions )
15
15
16
16
There is two idiomatic ways to secure a PHAR:
@@ -35,8 +35,8 @@ $phar->setSignatureAlgorithm($algo, $privateKey);
35
35
There is various algorithm available. The most "secure" one would be ` Phar::OPENSSL ` with an
36
36
OpenSSL private key. For instance:
37
37
38
- ```
39
- $ openssl genrsa -des3 -out acme-phar-private.pem 4096
38
+ ``` shell
39
+ openssl genrsa -des3 -out acme-phar-private.pem 4096
40
40
```
41
41
42
42
``` php
@@ -94,7 +94,7 @@ there is ways to void the signature:
94
94
file (the public key), but in the context the attacker could inject code to the PHAR this is unlikely to be a real
95
95
prevention measure.
96
96
97
- So to conclude, ** this security mechanism CANNOT prevent modifications of the archive itself.** It is NOT a reliable
97
+ So to conclude, ** this security mechanism CANNOT prevent modifications of the archive itself.** It is ** NOT** a reliable
98
98
protection measure.
99
99
100
100
The good news, there is a solution.
@@ -106,14 +106,15 @@ The good news, there is a solution.
106
106
107
107
The first step is to create a new GPG-key. You can either do that via a GUI or via the CLI like this:
108
108
109
- ```
110
- $ gpg --gen-key
109
+ ``` shell
110
+ gpg --gen-key
111
111
```
112
112
113
113
It will ask for some questions. It is recommended to use a passphrase (ideally generated and managed by a reputable
114
114
password manager). In the end, you will end up with something like this:
115
115
116
116
```
117
+ # $ gpg --gen-key output
117
118
pub ed25519 2023-10-21 [SC] [expires: 2026-10-20]
118
119
96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08
119
120
uid Théo Fidry <theo.fidry+phar-signing-example@example.com>
@@ -123,8 +124,8 @@ sub cv25519 2023-10-21 [E] [expires: 2026-10-20]
123
124
In this case the interesting part is ` 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08 ` which is the key ID. You can also check
124
125
the list of your GPG keys like so:
125
126
126
- ```
127
- $ gpg --list-secret-keys --keyid-format=long
127
+ ``` shell
128
+ gpg --list-secret-keys --keyid-format=long
128
129
129
130
#
130
131
# Other keys displayed too
@@ -135,22 +136,24 @@ uid [ultimate] Théo Fidry <theo.fidry+phar-signing-example@exam
135
136
ssb cv25519/765C0E3CCBC7D7D3 2023-10-21 [E] [expires: 2026-10-20]
136
137
```
137
138
138
- The interesting part is the ` 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08 ` which is the key-ID .
139
+ Like above, you see the key ID ` 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08 ` .
139
140
140
- To make the key accessible for others we should now send it to a keyserver† .
141
+ To make the key accessible for others we should now send it to a keyserver[ ^ 1 ] .
141
142
142
- ```
143
- $ gpg --keyserver keys.openpgp.org --send-key 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08
143
+ ``` shell
144
+ gpg --keyserver keys.openpgp.org --send-key 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08
144
145
```
145
146
146
- †: There is several OpenPGP Keyservers. It is recommended to push your keys to [ keys.openpgp.org] _ at least_ , but you
147
- can also push it to other servers if you wish to.
147
+ [ ^ 1 ] :
148
+
149
+ There is several OpenPGP Keyservers. It is recommended to push your keys to [ keys.openpgp.org] _ at least_ , but you
150
+ can also push it to other servers if you wish to.
148
151
149
152
You can also already generate a revocation certificate for the key. Should the key be compromised you can then send the
150
153
revocation certificate to the keyserver to invalidate the signing key.
151
154
152
- ```
153
- $ gpg --output revoke-96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08.asc --gen-revoke 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08
155
+ ``` shell
156
+ gpg --output revoke-96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08.asc --gen-revoke 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08
154
157
```
155
158
156
159
This will leave you with a revocation certificate in the file ` revoke-96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08.asc `
@@ -167,13 +170,15 @@ private GPG key.
167
170
168
171
In order to use the key to encrypt files, you need to first export it:
169
172
170
- ```
171
- $ gpg --export --armor 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08 > keys.asc
172
- $ gpg --export-secret-key --armor 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08 >> keys.asc
173
+ ``` shell
174
+ gpg --export --armor 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08 > keys.asc
175
+ gpg --export-secret-key --armor 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08 >> keys.asc
173
176
```
174
177
175
- That will leave the public and private key in a single file. Anyone that has that file can sign on your behalf! So keep
176
- that file secure at all times and make sure it never accidentally shows up in your git repository!
178
+ !!! warning
179
+
180
+ That will leave the public and private key in a single file. Anyone that has that file can sign on your behalf! So keep
181
+ that file secure at all times and make sure it never accidentally shows up in your git repository.
177
182
178
183
179
184
### Secure your encryption key
@@ -196,9 +201,9 @@ it is better to not keep that decrypted key around.
196
201
197
202
You first need to encrypt ` keys.asc.gpg ` into ` keys.asc ` :
198
203
199
- ```
204
+ ``` shell
200
205
# If you are locally:
201
- $ gpg keys.asc.gpg
206
+ gpg keys.asc.gpg
202
207
# In another environment: CI or other. You should use an environment variable
203
208
# or a temporary file to avoid printing the password in clear text.
204
209
echo $DECRYPT_KEY_PASSPHRASE | gpg --passphrase-fd 0 keys.asc.gpg
@@ -208,14 +213,14 @@ cat $(.decrypt-key-passphrase) | gpg --passphrase-fd 0 keys.asc.gpg
208
213
209
214
Import the decrypted key if it is not already present on the machine:
210
215
211
- ```
212
- $ gpg --batch --yes --import keys.asc
216
+ ``` shell
217
+ gpg --batch --yes --import keys.asc
213
218
```
214
219
215
220
Sign your file:
216
221
217
- ```
218
- $ gpg \
222
+ ``` shell
223
+ gpg \
219
224
--batch \
220
225
--passphrase=" $GPG_KEY_96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08_PASSPHRASE " \
221
226
--local-user 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08 \
@@ -241,12 +246,12 @@ documentation:
241
246
gpg --keyserver hkps://keys.openpgp.org --recv-keys 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08
242
247
```
243
248
244
- However not everyone expose what is their GPG key ID. So sometimes to avoid bad surprises, you
249
+ However not everyone exposes what is their GPG key ID. So sometimes to avoid bad surprises, you
245
250
can look up for similar issuers to the key ID given by the ` .asc ` :
246
251
247
- ```
252
+ ``` shell
248
253
# Verify the signature
249
- $ gpg --verify bin/command.phar.asc bin/command.phar
254
+ gpg --verify bin/command.phar.asc bin/command.phar
250
255
251
256
# Example of output:
252
257
gpg: Signature made Sat 21 Oct 16:58:05 2023 CEST
@@ -256,19 +261,21 @@ gpg: Good signature from "Théo Fidry <theo.fidry+phar-signing-example@example.c
256
261
257
262
If the key ID was not provided before, you can try to look it up to check it was properly registered to a keyserver:
258
263
259
- ```
260
- $ gpg --keyserver https://keys.openpgp.org --search-keys "theo.fidry+phar-signing-example@example.com"
264
+ ``` shell
265
+ gpg --keyserver https://keys.openpgp.org --search-keys " theo.fidry+phar-signing-example@example.com"
261
266
```
262
267
263
- Also note that when dealing with PHARs, the above steps are automatically done for you by [ PHIVE] [ phive ] .
268
+ !!! info
269
+
270
+ Also note that when dealing with PHARs, the above steps are automatically done for you by [PHIVE][phive].
264
271
265
272
266
273
## Automatically sign in GitHub Actions
267
274
268
275
The first step is to add [ environment secrets to your repository] [ github-environment-secrets ] :
269
276
270
- ```
271
- $ gpg --export-secret-key --armor 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08
277
+ ``` shell
278
+ gpg --export-secret-key --armor 96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08
272
279
# Paste the content into a secret environment variable
273
280
GPG_KEY_96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08
274
281
@@ -277,15 +284,17 @@ GPG_KEY_96C8013A3CC293C465EE3FBB03B2F4DF7A20DF08_PASSPHRASE
277
284
```
278
285
279
286
Then you need to:
287
+
280
288
- Build your PHAR
281
289
- Import the GPG key
282
290
- Sign your PHAR
283
291
- Publish your PHAR
284
292
285
293
I highly recommend to build your PHAR as part of your regular workflows. Then the other steps can be enable on release
286
- only. The following is an example of GitHub workflow:
294
+ only. The following is an example of [ GitHub workflow] [ github-workflow ] :
287
295
288
296
``` yaml
297
+ # .github/workflows/release.yaml
289
298
name : Release
290
299
291
300
on :
@@ -380,5 +389,6 @@ Credits:
380
389
[box-release-workflow]: https://github.com/box-project/box/blob/main/.github/workflows/release.yaml
381
390
[keys.openpgp.org]: https://keys.openpgp.org/about
382
391
[github-environment-secrets]: https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions
392
+ [github-workflow]: https://docs.github.com/en/actions/using-workflows
383
393
[phive]: https://phar.io/
384
394
[jar]: https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jarGuide.html
0 commit comments