Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 764b586

Browse files
committed
Added PGP clearsign verifier
1 parent 2889410 commit 764b586

File tree

8 files changed

+227
-4
lines changed

8 files changed

+227
-4
lines changed

‎app/test/cc/arduino/contributions/SignatureVerifierTest.java‎

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@
2929

3030
package cc.arduino.contributions;
3131

32-
import org.junit.Before;
33-
import org.junit.Test;
32+
import staticorg.junit.Assert.assertFalse;
33+
import staticorg.junit.Assert.assertTrue;
3434

3535
import java.io.File;
3636

37-
import staticorg.junit.Assert.assertFalse;
38-
import staticorg.junit.Assert.assertTrue;
37+
import org.junit.Before;
38+
import org.junit.Test;
3939

4040
public class SignatureVerifierTest {
4141

@@ -62,4 +62,24 @@ public void testSignatureFailingVerification() throws Exception {
6262
File sign = new File(SignatureVerifierTest.class.getResource("./package_index.json.sig").getFile());
6363
assertFalse(verifier.verify(fakeSignedFile, sign));
6464
}
65+
66+
@Test
67+
public void testClearTextSignatureVerification() throws Exception {
68+
File signedFile = new File(SignatureVerifierTest.class.getResource("./text.txt.asc").getFile());
69+
assertTrue(verifier.verifyCleartextSignature(signedFile));
70+
File signedFile2 = new File(SignatureVerifierTest.class.getResource("./escaped-text.txt.asc").getFile());
71+
assertTrue(verifier.verifyCleartextSignature(signedFile2));
72+
File oneBlankLines = new File(SignatureVerifierTest.class.getResource("./one-blank-line.txt.asc").getFile());
73+
assertTrue(verifier.verifyCleartextSignature(oneBlankLines));
74+
File twoBlankLines = new File(SignatureVerifierTest.class.getResource("./two-blank-lines.txt.asc").getFile());
75+
assertTrue(verifier.verifyCleartextSignature(twoBlankLines));
76+
File noBlankLines = new File(SignatureVerifierTest.class.getResource("./no-blank-lines.txt.asc").getFile());
77+
assertTrue(verifier.verifyCleartextSignature(noBlankLines));
78+
}
79+
80+
@Test
81+
public void testClearTextSignatureFailingVerification() throws Exception {
82+
File signedFile = new File(SignatureVerifierTest.class.getResource("./wrong-text.txt.asc").getFile());
83+
assertFalse(verifier.verifyCleartextSignature(signedFile));
84+
}
6585
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
-----BEGIN PGP SIGNED MESSAGE-----
2+
Hash: SHA512
3+
4+
- -
5+
- -
6+
- - abc
7+
- -- abc
8+
helllo!!!!
9+
10+
11+
12+
13+
14+
-----BEGIN PGP SIGNATURE-----
15+
16+
iQIzBAEBCgAdFiEEMmVnwcayiN8yywYalfpvQ+IRiMQFAl6CcaUACgkQlfpvQ+IR
17+
iMQD9w/+KA2ZusmFnpt7dXTy/6ohNCijMp3pFSVsBzGWBDpGJjYfwek2N8HssXIa
18+
Tq0uzCiTm1Z4kn+SWjIHxKzdihUi9mwkMCqdhNTZN0+FKXc+c358KUYXOlyigOmX
19+
256bG7Ep2P/3ZBzhvVC5WKLIwYhq6cj9fSnt26XP02qt/9ztczGJHDpEfIhPA0LI
20+
PYnUUo4KftQzHp41EPENIyLTkT1YzhypnIHCv2mG8qql+W9blx1eO8gIUGmzQQ0y
21+
CnTY0AIvmrAGd5WQWwKpKy5aLpWDmIW/zSSoDc7jC74i2V6n5Y+Fqq++SVDvIApd
22+
yP+BmL6pDfZf9cV8nDQOI9Jd+/JT3tUct5js9lDhj74g1ZGobx06kZPv/ojbSE42
23+
jJi75HQ3NDG8dBDMtYzrDeO0QhcpT94LNTdZ8IdR5jCf3I9SkpHB6sb27elVgcBb
24+
stXLRhrf0se2U2pI3CGDkjumm04cDOhY9tLt2CHMlL9yl9LZejyT3xUoLGAy1Ird
25+
Jw6knZM5O/bWzFq1bxlqgz6EspafNy+ZM8/1s+b9ecxKkds7UEZLpOVd+QYMO6i1
26+
lxm4ZQqRoTiIcVxzhwChd41zxPw9bMNq03prBMnetJ9tvb76qgGcCvRh/ANYWBfa
27+
2zeH3UGaOyMB79oKOSw0qzXkFA+0qXzROObVWTzjGOPZJtkfaA8=
28+
=BqjQ
29+
-----END PGP SIGNATURE-----
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-----BEGIN PGP SIGNED MESSAGE-----
2+
Hash: SHA512
3+
4+
hello
5+
-----BEGIN PGP SIGNATURE-----
6+
7+
iQIzBAEBCgAdFiEEMmVnwcayiN8yywYalfpvQ+IRiMQFAl6C/AsACgkQlfpvQ+IR
8+
iMQYUA//SEHkb60xiXyP8TfTfxiJORr7ltvLtL7N9IwpnrkeKdvvrxC71O5U4kdf
9+
Ek5XUALXUPArWJHByKBZ3saQapRPMUNbsLDG9QqtIffORqgPnfPAgMiGYceIaT1o
10+
QChspIQRL6xt6k8c6o2M5R7CBMjiDqaldpJHsq3kcjcgHBmJFPdDdhjA2D9s4mCo
11+
nymy3PqLcZ4RARrED61VlF4hcVHv5BHPnDZDXug3oGiR2EQTpdQgvBg/rL2xiVHl
12+
MgZ6/5owF6omeNM30JNPQfNdDnV2jDhxILfjY2Rqyj9zClrnZB6qox6h1RoSKIFy
13+
UkBUAs3WapZMqR2UKq3K7dL8cqUKoOFdSpd/R2T4ZBC/6exiwVnbDGa161ur8f4/
14+
55RxAe/VE+75bC7HI3jNAUn7xGMUGBWgTKh+xTnyh50BHifmCIzyLOgRWds/rvMH
15+
PT0fmtbTWhjrJOfuhi15uSJ0Lvq/XuM/z/aIgeZHaIBnIxvRYUOdP6Rz1xKHmc2q
16+
+puI2FxpbENUyt8TNlrnHJeq72UubVIRJ08CE2iiuWjP+1jFxPYA1tWBYrqtbK7y
17+
2ZPq5c+vy8LMij/SfZkeOa388Ss3lXr5CTJ+O2VMLellyCdUd0G47T26umCr6zaF
18+
jX1huU0rfA+vGLVfr1Z2nexX0r7kwebkz/PWIO1+Kc41gBY+cek=
19+
=Rejh
20+
-----END PGP SIGNATURE-----
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-----BEGIN PGP SIGNED MESSAGE-----
2+
Hash: SHA512
3+
4+
hello
5+
6+
-----BEGIN PGP SIGNATURE-----
7+
8+
iQIzBAEBCgAdFiEEMmVnwcayiN8yywYalfpvQ+IRiMQFAl6C/E8ACgkQlfpvQ+IR
9+
iMS/iA/+KxhaOTokmXTKgSkZwaCdPwTIdcfIVWMsK6mxXcSeWtmQpCxMyH3sudaA
10+
MvVg8qMHTTiYbFD5TMBF79Eu3nJuLemnm7WbpQMAQ7/Ay8qDrH6MIIqeR6TLa6CO
11+
VQw2a9H3AoqVxBtH0y6vVk+mOnr8NnZA3XoT0B2TuLApqY4uFt9quHBkrycHdXve
12+
6++EyiYeDgY6oG1bAR0S/peFhCL45CId9xJe5RIHT7aFoDKw78LPcfoTLdKCtzzE
13+
CdX1IpzP/tOVlv0LTNPWQQeRQ07BKpquQnQbzuAgVFbLf27kI2e+AxjIdmozEjO9
14+
rk9Za0tpKYCYT5lF9zfmaCWzkhTfrjB8OPXWYHjozzv4aUhfvgQ+TF9dynWU4ct8
15+
ACRkb+bp+ENZVy0/1VdDDs3wrFnMHuZyrBWXNI8sBu6f1JSG4ddgy7NfPveOJEdG
16+
wg/4mxzSnBQ7jogRaJLioC+mjxulmN1FCoDMwphOLkmaIX1qIL3OxkEBfSzpfkfe
17+
wAYhjSqLHHXwx0W0resDahC2L81gBnTbf0yP1jEWjnSs96AqwvLSAj0gyC4BtVoN
18+
LSgYDFeNitoBMDx8osi0KjLydOzbQW9L5u//Rm/Q/8/p7+4u/X3X8EWHULHIsrRW
19+
T9M6jun8zTr9OLAk9W1T76Yu2Wyu+ps6f6iAeSlvqTTpr3+j2W4=
20+
=0JE+
21+
-----END PGP SIGNATURE-----
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-----BEGIN PGP SIGNED MESSAGE-----
2+
Hash: SHA512
3+
4+
helllo!!!!
5+
6+
-----BEGIN PGP SIGNATURE-----
7+
8+
iQIzBAEBCgAdFiEEMmVnwcayiN8yywYalfpvQ+IRiMQFAl6CPtwACgkQlfpvQ+IR
9+
iMS8AA//dCIbYCPwTdOFf3YRFO2Z7YSgAgEpctcH1UW9IaZpGlfZDqiskgNT5zWx
10+
ooW0EqVagyyY+1Fips4a52/urQmbQ+0RIU6r4zDUvyMoN/f41jFKd1eY365oqORo
11+
G5avMFhZ7PwbYXKhDeVQrDCRSYSvWYyRXH97VpFvo/SSuvB7KWvlTFFK9rt1xysx
12+
rjikCqMWuPeReSclLCMCGQGjcJExNsu7E9l55NcJMOP8a3yVlY9b1LwH5nuVXOfw
13+
UvSzHK2K16O3COb0otWN8VZHB0x2y3Y1boIF2J/Wt9zBaB/d4cmacwL4KLHiw7KR
14+
q5YzDfEpmwMM9S5QLsLPYBWr9B1XSQ+PrylPSha1NnDStr/RkFtwVsags3igJu5E
15+
Ye+aJra6D/VREFc/IQYsEmcDHYdKp3CNJn/BdNwTDI4BIdj4lBDd6lVrcL+Id8pl
16+
ivdk1bV/575eTH9cDf65aF/lmd/z6dGNLcke4N76n8g/xjAuSkN7FDm91KGv9oCJ
17+
e0eO0+GDJbfMHz61vQ1DPfUWqyQLC3z9OeX+bUvqSb1Xy9i2OI0FlY3GMtwDONto
18+
qShjcbeXXYt74bINsAEV78pSoYPHc2rYco1/qrAL1bYY9Hngy3FvgD7mVNd7nC/J
19+
buFQ4Ek07urJpA9lw8o/z49O7iGisc8UXuPeHY2z7LmUuCvKpKI=
20+
=DKVh
21+
-----END PGP SIGNATURE-----
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
-----BEGIN PGP SIGNED MESSAGE-----
2+
Hash: SHA512
3+
4+
hello
5+
6+
7+
-----BEGIN PGP SIGNATURE-----
8+
9+
iQIzBAEBCgAdFiEEMmVnwcayiN8yywYalfpvQ+IRiMQFAl6C/H8ACgkQlfpvQ+IR
10+
iMQD9RAAk34n7WegdXdreKLU5nAkx9/lcPwZYRcwTeV6pgroxQ3XuC3oEqUwDQtD
11+
RLT+Gc+1j7XMGxTIJtHhpwpJk2IeT5x/lfqpMwpHoJUEOA/QZ7YtUTUj5aqc3bJV
12+
QEWXrNyceqaYkUguR7gk0ahtniTuaj9WaixRpxiu9+AMht74g0iZm99h2fpgiIb1
13+
7M2SdMbmyW1mK7BFN9Cghz/8NedV6TeKpQnWWpN+hdO1fsjGIVRNRfTMod7gL6QK
14+
KhPa3eQW+yxlEshKZwQJwIe3vcgquK6bAl/p20EU7+2ytnFd3zBhcCFJtC6fV+zF
15+
s89BOAoAJPRaBKbQp01IsBB5mNZUxKFOa+e94tFLmaaI7KhHB7oQ7Qnx+hTgq7bG
16+
9PRza0bHMkBPumACM8FNjOlzJNY5eTnfDcAq2kgaAdoX5LFLrIiYUNtz9gmIIHNj
17+
xekG9LB3WUv013jPSOUnbmGkch0VvVgFvcsOtGWTHp+VlZLOWZjXkO+Cco2qWcVr
18+
F7ckPTXs+nzoOTVsYZLfN8g92y2sT548+Q9bCtT1QStGCSTyNF1o0JW9Ih1hsSkn
19+
qJVgo8wGO45mTT4GJ6VWUkFkAjoaZM14F70CJp0eLw5PSxDIkSsmkL7CYwGeA+6N
20+
UtKIJ1ZoFMElW5bMuSayLEjtC9RkGILjplkiFY+h7gJd/vitTvI=
21+
=g/9c
22+
-----END PGP SIGNATURE-----
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-----BEGIN PGP SIGNED MESSAGE-----
2+
Hash: SHA512
3+
4+
!!helllo!!!!
5+
6+
-----BEGIN PGP SIGNATURE-----
7+
8+
iQIzBAEBCgAdFiEEMmVnwcayiN8yywYalfpvQ+IRiMQFAl6CPtwACgkQlfpvQ+IR
9+
iMS8AA//dCIbYCPwTdOFf3YRFO2Z7YSgAgEpctcH1UW9IaZpGlfZDqiskgNT5zWx
10+
ooW0EqVagyyY+1Fips4a52/urQmbQ+0RIU6r4zDUvyMoN/f41jFKd1eY365oqORo
11+
G5avMFhZ7PwbYXKhDeVQrDCRSYSvWYyRXH97VpFvo/SSuvB7KWvlTFFK9rt1xysx
12+
rjikCqMWuPeReSclLCMCGQGjcJExNsu7E9l55NcJMOP8a3yVlY9b1LwH5nuVXOfw
13+
UvSzHK2K16O3COb0otWN8VZHB0x2y3Y1boIF2J/Wt9zBaB/d4cmacwL4KLHiw7KR
14+
q5YzDfEpmwMM9S5QLsLPYBWr9B1XSQ+PrylPSha1NnDStr/RkFtwVsags3igJu5E
15+
Ye+aJra6D/VREFc/IQYsEmcDHYdKp3CNJn/BdNwTDI4BIdj4lBDd6lVrcL+Id8pl
16+
ivdk1bV/575eTH9cDf65aF/lmd/z6dGNLcke4N76n8g/xjAuSkN7FDm91KGv9oCJ
17+
e0eO0+GDJbfMHz61vQ1DPfUWqyQLC3z9OeX+bUvqSb1Xy9i2OI0FlY3GMtwDONto
18+
qShjcbeXXYt74bINsAEV78pSoYPHc2rYco1/qrAL1bYY9Hngy3FvgD7mVNd7nC/J
19+
buFQ4Ek07urJpA9lw8o/z49O7iGisc8UXuPeHY2z7LmUuCvKpKI=
20+
=DKVh
21+
-----END PGP SIGNATURE-----

‎arduino-core/src/cc/arduino/contributions/SignatureVerifier.java‎

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,20 @@
3131

3232
import java.io.File;
3333
import java.io.FileInputStream;
34+
import java.io.FileNotFoundException;
3435
import java.io.IOException;
3536
import java.io.InputStream;
3637

3738
import org.apache.commons.compress.utils.IOUtils;
39+
import org.bouncycastle.bcpg.ArmoredInputStream;
3840
import org.bouncycastle.openpgp.PGPException;
3941
import org.bouncycastle.openpgp.PGPObjectFactory;
4042
import org.bouncycastle.openpgp.PGPPublicKey;
4143
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
4244
import org.bouncycastle.openpgp.PGPSignature;
4345
import org.bouncycastle.openpgp.PGPSignatureList;
4446
import org.bouncycastle.openpgp.PGPUtil;
47+
import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory;
4548
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
4649
import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider;
4750

@@ -127,4 +130,70 @@ private PGPPublicKey readPublicKey(long id) throws IOException, PGPException {
127130
}
128131
}
129132

133+
public String[] extractTextFromCleartextSignature(File inFile) throws FileNotFoundException, IOException {
134+
try (ArmoredInputStream in = new ArmoredInputStream(new FileInputStream(inFile))) {
135+
return extractTextFromCleartextSignature(in);
136+
}
137+
}
138+
139+
public boolean verifyCleartextSignature(File inFile) {
140+
try (ArmoredInputStream in = new ArmoredInputStream(new FileInputStream(inFile))) {
141+
String[] clearTextLines = extractTextFromCleartextSignature(in);
142+
int clearTextSize = clearTextLines.length;
143+
144+
JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(in);
145+
PGPSignatureList p3 = (PGPSignatureList) pgpFact.nextObject();
146+
PGPSignature sig = p3.get(0);
147+
PGPPublicKey publicKey = readPublicKey(sig.getKeyID());
148+
149+
sig.init(new BcPGPContentVerifierBuilderProvider(), publicKey);
150+
for (int i = 0; i < clearTextSize; i++) {
151+
sig.update(clearTextLines[i].getBytes());
152+
if (i + 1 < clearTextSize) {
153+
// https://tools.ietf.org/html/rfc4880#section-7
154+
// Convert all line endings to '\r\n'
155+
sig.update((byte) '\r');
156+
sig.update((byte) '\n');
157+
}
158+
}
159+
return sig.verify();
160+
} catch (Exception e) {
161+
e.printStackTrace();
162+
return false;
163+
}
164+
}
165+
166+
private String[] extractTextFromCleartextSignature(ArmoredInputStream in) throws FileNotFoundException, IOException {
167+
// https://tools.ietf.org/html/rfc4880#section-7
168+
// ArmoredInputStream does unescape dash-escaped string in armored text and skips
169+
// all headers. To calculate the signature we still need to:
170+
// 1. handle different line endings \n or \n\r or \r\n
171+
// 2. remove trailing whitespaces from each line (' ' and '\t')
172+
// 3. remove the latest line ending
173+
174+
String clearText = "";
175+
for (;;) {
176+
int c = in.read();
177+
// in.isClearText() refers to the PREVIOUS byte read
178+
if (c == -1 || !in.isClearText()) {
179+
break;
180+
}
181+
// 1. convert all line endings to '\r\n'
182+
if (c == '\r') {
183+
continue;
184+
}
185+
clearText += (char) c;
186+
}
187+
188+
// 3. remove the latest line ending
189+
if (clearText.endsWith("\n")) {
190+
clearText = clearText.substring(0, clearText.length() - 1);
191+
}
192+
String[] lines = clearText.split("\n", -1);
193+
for (int i = 0; i < lines.length; i++) {
194+
// 2. remove trailing whitespaces from each line (' ' and '\t')
195+
lines[i] = lines[i].replaceAll("[ \\t]+$", "");
196+
}
197+
return lines;
198+
}
130199
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /