mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-23 11:27:57 +01:00
Merge branch 'parse_public_key_ring_collection_from_armored_source'
This commit is contained in:
commit
d0a162ce74
3 changed files with 262 additions and 2 deletions
|
@ -27,6 +27,7 @@ import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
|||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
||||
import org.bouncycastle.openpgp.PGPUtil;
|
||||
import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
|
||||
import org.pgpainless.implementation.ImplementationFactory;
|
||||
|
||||
public class KeyRingReader {
|
||||
|
@ -96,7 +97,7 @@ public class KeyRingReader {
|
|||
public static PGPPublicKeyRingCollection readPublicKeyRingCollection(@Nonnull InputStream inputStream)
|
||||
throws IOException, PGPException {
|
||||
return new PGPPublicKeyRingCollection(
|
||||
PGPUtil.getDecoderStream(inputStream),
|
||||
getDecoderStream(inputStream),
|
||||
ImplementationFactory.getInstance().getKeyFingerprintCalculator());
|
||||
}
|
||||
|
||||
|
@ -109,7 +110,7 @@ public class KeyRingReader {
|
|||
public static PGPSecretKeyRingCollection readSecretKeyRingCollection(@Nonnull InputStream inputStream)
|
||||
throws IOException, PGPException {
|
||||
return new PGPSecretKeyRingCollection(
|
||||
PGPUtil.getDecoderStream(inputStream),
|
||||
getDecoderStream(inputStream),
|
||||
ImplementationFactory.getInstance().getKeyFingerprintCalculator());
|
||||
}
|
||||
|
||||
|
@ -132,4 +133,23 @@ public class KeyRingReader {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hacky workaround for #96.
|
||||
* For {@link PGPPublicKeyRingCollection#PGPPublicKeyRingCollection(InputStream, KeyFingerPrintCalculator)}
|
||||
* or {@link PGPSecretKeyRingCollection#PGPSecretKeyRingCollection(InputStream, KeyFingerPrintCalculator)}
|
||||
* to read all PGPKeyRings properly, we apparently have to make sure that the {@link InputStream} that is given
|
||||
* as constructor argument is a {@link PGPUtil.BufferedInputStreamExt}.
|
||||
* Since {@link PGPUtil#getDecoderStream(InputStream)} will return an {@link org.bouncycastle.bcpg.ArmoredInputStream}
|
||||
* if the underlying input stream contains armored data, we have to nest two method calls to make sure that the
|
||||
* end-result is a {@link PGPUtil.BufferedInputStreamExt}.
|
||||
*
|
||||
* This is a hacky solution.
|
||||
*
|
||||
* @param inputStream input stream
|
||||
* @return BufferedInputStreamExt
|
||||
*/
|
||||
private static InputStream getDecoderStream(InputStream inputStream) throws IOException {
|
||||
return PGPUtil.getDecoderStream(PGPUtil.getDecoderStream(inputStream));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright 2021 Paul Schaub
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pgpainless.key.parsing;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.implementation.ImplementationFactory;
|
||||
import org.pgpainless.key.util.KeyRingUtils;
|
||||
|
||||
class KeyRingReaderTest {
|
||||
|
||||
@Test
|
||||
public void assertThatPGPUtilsDetectAsciiArmoredData() throws IOException, PGPException {
|
||||
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("pub_keys_10_pieces.asc");
|
||||
|
||||
InputStream possiblyArmored = PGPUtil.getDecoderStream(PGPUtil.getDecoderStream(inputStream));
|
||||
|
||||
PGPPublicKeyRingCollection collection = new PGPPublicKeyRingCollection(
|
||||
possiblyArmored, ImplementationFactory.getInstance().getKeyFingerprintCalculator());
|
||||
assertEquals(10, collection.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void publicKeyRingCollectionFromStream() throws IOException, PGPException {
|
||||
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("pub_keys_10_pieces.asc");
|
||||
PGPPublicKeyRingCollection rings = PGPainless.readKeyRing().publicKeyRingCollection(inputStream);
|
||||
assertEquals(10, rings.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void publicKeyRingCollectionFromNotArmoredStream() throws IOException, PGPException,
|
||||
InvalidAlgorithmParameterException, NoSuchAlgorithmException {
|
||||
Collection<PGPPublicKeyRing> collection = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("user_" + i + "@encrypted.key");
|
||||
collection.add(KeyRingUtils.publicKeyRingFrom(secretKeys));
|
||||
}
|
||||
|
||||
PGPPublicKeyRingCollection originalRings = new PGPPublicKeyRingCollection(collection);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
originalRings.encode(out);
|
||||
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(out.toByteArray());
|
||||
PGPPublicKeyRingCollection parsedRings = PGPainless.readKeyRing().publicKeyRingCollection(inputStream);
|
||||
assertEquals(10, parsedRings.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void publicKeyRingCollectionFromString() throws IOException, PGPException, URISyntaxException {
|
||||
URL resource = getClass().getClassLoader().getResource("pub_keys_10_pieces.asc");
|
||||
String armoredString = new String(Files.readAllBytes(new File(resource.toURI()).toPath()));
|
||||
InputStream inputStream = new ByteArrayInputStream(armoredString.getBytes(StandardCharsets.UTF_8));
|
||||
PGPPublicKeyRingCollection rings = PGPainless.readKeyRing().publicKeyRingCollection(inputStream);
|
||||
assertEquals(10, rings.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void publicKeyRingCollectionFromBytes() throws IOException, PGPException, URISyntaxException {
|
||||
URL resource = getClass().getClassLoader().getResource("pub_keys_10_pieces.asc");
|
||||
byte[] bytes = Files.readAllBytes(new File(resource.toURI()).toPath());
|
||||
InputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
|
||||
PGPPublicKeyRingCollection rings = PGPainless.readKeyRing().publicKeyRingCollection(byteArrayInputStream);
|
||||
assertEquals(10, rings.size());
|
||||
}
|
||||
|
||||
}
|
139
pgpainless-core/src/test/resources/pub_keys_10_pieces.asc
Normal file
139
pgpainless-core/src/test/resources/pub_keys_10_pieces.asc
Normal file
|
@ -0,0 +1,139 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: PGPainless
|
||||
|
||||
mDMEYFHdchYJKwYBBAHaRw8BAQdAyfub9GUlTvuIicT6gnLTe5IK7ulwRjh6AmNW
|
||||
9pGVpb60E2ZyZXNoQGVuY3J5cHRlZC5rZXmIeAQTFgoAIAUCYFHdcgIbAwUWAgMB
|
||||
AAQLCQgHBRUKCQgLAh4BAhkBAAoJEJSMRVGPhjdgOUABAIU80GMm2v8oWrQyctAi
|
||||
VhpkRhNXFBoxzV2Ocg47eWukAQCHjjA10tTIzq5umoNXrb1vLXmubzT77fXJwFA2
|
||||
qUonD7g4BGBR3XISCisGAQQBl1UBBQEBB0AZuOnF7dxM/+U9kZtHkf4ze9mlm7mF
|
||||
nzt2ugq/LrgLKAMBCAeIdQQYFgoAHQUCYFHdcgIbDAUWAgMBAAQLCQgHBRUKCQgL
|
||||
Ah4BAAoJEJSMRVGPhjdghv8BAMYlDl20Kn3K1KWFBSU8bw7OZsgz5ppzEywU/xpr
|
||||
v2yHAP470or42l5oTh/xAnWQEReD0d5pnh5fIKkeWBQTL7Y9Bg==
|
||||
=L01J
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: PGPainless
|
||||
|
||||
mDMEYFHdchYJKwYBBAHaRw8BAQdA3zRVckfne2fxGDOv5c2Tm7C4Azxbc+CZKP1R
|
||||
+XjpLKG0E2ZyZXNoQGVuY3J5cHRlZC5rZXmIeAQTFgoAIAUCYFHdcgIbAwUWAgMB
|
||||
AAQLCQgHBRUKCQgLAh4BAhkBAAoJEBOTT2Wz+JaqlwwA/3k6FiMD9hsPATpPgsmB
|
||||
dG6oz/pklaMlUvEzCh7NFRQqAP40nX6T3L4UwYbrvm4FXTle3DaL98DfFjH8ox1N
|
||||
e/ziC7g4BGBR3XISCisGAQQBl1UBBQEBB0BRwE/EJ/ocQ3nqm4jv8tB0nYYliJ72
|
||||
tvDVQhsD4mQLIAMBCAeIdQQYFgoAHQUCYFHdcgIbDAUWAgMBAAQLCQgHBRUKCQgL
|
||||
Ah4BAAoJEBOTT2Wz+JaqztIBAJvwyo0pw+q+48MYd0yIKRavkJ2Y71msPwSQ7Tnj
|
||||
gK7ZAQDW9L8pc9m1WISpI4HqVUGBbiaEm/U9vdNZ22fiehK+Dw==
|
||||
=F7rW
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: PGPainless
|
||||
|
||||
mDMEYFHdchYJKwYBBAHaRw8BAQdA4N4vZfhHcDvneIkPyTnBt4Ms3MSJAUwnxKKa
|
||||
hFs7tKS0E2ZyZXNoQGVuY3J5cHRlZC5rZXmIeAQTFgoAIAUCYFHdcgIbAwUWAgMB
|
||||
AAQLCQgHBRUKCQgLAh4BAhkBAAoJEONPfCWrUaykZC8BAJ0QAfFQAT4rSx3SWc8I
|
||||
FTHIflpj6G9OiV5EZcbDlUArAP0XtetsnNdba5wpeITZpL+/L3lgeb9pphr/rA/8
|
||||
/LLYDbg4BGBR3XISCisGAQQBl1UBBQEBB0DDwrx6U+u5yTlagwJHlSenorBjF6B2
|
||||
dAhNwblxhGA8fQMBCAeIdQQYFgoAHQUCYFHdcgIbDAUWAgMBAAQLCQgHBRUKCQgL
|
||||
Ah4BAAoJEONPfCWrUaykxQgBANUWnD5V2HhWTmi0ArVNKivW4Mvtj8GnH1m37qPp
|
||||
3D8VAP9SLOQrdGj1kFBtQSefkUCgMHdT1cddL919y8nRIevdAw==
|
||||
=9/eE
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: PGPainless
|
||||
|
||||
mDMEYFHdchYJKwYBBAHaRw8BAQdAflONZMOFFXT8HEwrjeRowixJ/CQwu1jF8WIf
|
||||
I4MYreq0E2ZyZXNoQGVuY3J5cHRlZC5rZXmIeAQTFgoAIAUCYFHdcgIbAwUWAgMB
|
||||
AAQLCQgHBRUKCQgLAh4BAhkBAAoJEGUsIC1Do6/1JisBAKTbbh6CaxhR9C0GqGMq
|
||||
Bd7y36wkd+qw7MyR63dUj/6MAQCkt+4h/YbiWnMFL1pLY+u5rERyyT4zDlZTDDV0
|
||||
vHsUB7g4BGBR3XISCisGAQQBl1UBBQEBB0AEFOE5+gHfw50UxFxY2MGT6e/M2oUB
|
||||
MBaOsIsVOPuZZwMBCAeIdQQYFgoAHQUCYFHdcgIbDAUWAgMBAAQLCQgHBRUKCQgL
|
||||
Ah4BAAoJEGUsIC1Do6/1EusBAL/IRKILeXCwAnXGfpnO3smCFSsGtCYJ1rhVaYhj
|
||||
zeVtAP47EXBKYvhbHgRy+Qx2BMFXX+VGFA2hWHZbo9OhbPpTAg==
|
||||
=cCbp
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: PGPainless
|
||||
|
||||
mDMEYFHdchYJKwYBBAHaRw8BAQdAYXkCPGptUC4P0LeQCC0kzi5PnzcZAFfX8S5b
|
||||
t8hRITy0E2ZyZXNoQGVuY3J5cHRlZC5rZXmIeAQTFgoAIAUCYFHdcgIbAwUWAgMB
|
||||
AAQLCQgHBRUKCQgLAh4BAhkBAAoJEIJgTO3chyrRB2UA+wfyFgnPEd8xkAwlPPJ7
|
||||
Bo0Ou6qFWzgigG1mGw2yHfogAQD5SW73I2bByhyP8LfyYRSQGjM6msxkECVDEVUw
|
||||
/hxaCbg4BGBR3XISCisGAQQBl1UBBQEBB0DUh3Sai70XUwzPQpe2mqppwn9ApUCk
|
||||
hStE1Giy4bzNdgMBCAeIdQQYFgoAHQUCYFHdcgIbDAUWAgMBAAQLCQgHBRUKCQgL
|
||||
Ah4BAAoJEIJgTO3chyrRgusA/3TbfgIiRL3Ype2LlfEZ2evyo1T8hQlH5yOmbKGW
|
||||
UxOIAQDWufEmTWpeV+bWfSkcb1C7dU8wSvM78GvAMMESrxozCw==
|
||||
=stfa
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: PGPainless
|
||||
|
||||
mDMEYFHdchYJKwYBBAHaRw8BAQdAPybWtX75zj1GIjPEITKpjyG7MccvPLoU9HrU
|
||||
d3QwWmO0E2ZyZXNoQGVuY3J5cHRlZC5rZXmIeAQTFgoAIAUCYFHdcgIbAwUWAgMB
|
||||
AAQLCQgHBRUKCQgLAh4BAhkBAAoJEI1HfhWTysXbKqAA/igvr9eCnSGKzYD6KnrZ
|
||||
wd6MKM4OD5NsiX6DkCew/AaPAQDK9lyRdibbR52CNVeueVYkCbMaPohChf9nvx2M
|
||||
4XLcBbg4BGBR3XISCisGAQQBl1UBBQEBB0AfsNRAXC/naStyC9666gAOtgEOqQ3e
|
||||
XhxgfITehCabBQMBCAeIdQQYFgoAHQUCYFHdcgIbDAUWAgMBAAQLCQgHBRUKCQgL
|
||||
Ah4BAAoJEI1HfhWTysXb2AIBALmv9be7RWcRnHvvVw3sCqzH5P3dQlOiYkzp++wj
|
||||
HFBQAQC1XRes+v9nawkkQPLL6W6TTdJsrqdRTghLO9oWad7DAQ==
|
||||
=ILBW
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: PGPainless
|
||||
|
||||
mDMEYFHdchYJKwYBBAHaRw8BAQdAtW6tSlO27WD5JWBmfzfmy/VLcB7yfPdvqxux
|
||||
byKVk6O0E2ZyZXNoQGVuY3J5cHRlZC5rZXmIeAQTFgoAIAUCYFHdcgIbAwUWAgMB
|
||||
AAQLCQgHBRUKCQgLAh4BAhkBAAoJEP9Vh6wldIQkKwABAKC8xwjkT4qeOWV2bKu/
|
||||
3C7a1T4hlhQtRqSiFcdK9pDrAQCAdN1+XDkoKz6b717PcRc+6vhUJWGO4GaoCucS
|
||||
cIuiD7g4BGBR3XISCisGAQQBl1UBBQEBB0C5b5/Zh4wZUOqihUebwjS8djSDvn2h
|
||||
AuzD3w0FKXgiGQMBCAeIdQQYFgoAHQUCYFHdcgIbDAUWAgMBAAQLCQgHBRUKCQgL
|
||||
Ah4BAAoJEP9Vh6wldIQkjxIBAOx8lL/3oYnA5CxueagTmGJSl8CvFiirnfzDF34/
|
||||
zCx6AP9viCSUII6a9z2vphe7XWRm1VOZNDG4R5Pzg2x32B7tAQ==
|
||||
=oiKv
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: PGPainless
|
||||
|
||||
mDMEYFHdchYJKwYBBAHaRw8BAQdAo0Hx0pRqnU4mZwfK3CgwzV53QHhMIfltKOM8
|
||||
i6kzIN60E2ZyZXNoQGVuY3J5cHRlZC5rZXmIeAQTFgoAIAUCYFHdcgIbAwUWAgMB
|
||||
AAQLCQgHBRUKCQgLAh4BAhkBAAoJEMrL/Yggs136P+kA/3doLAoG5jju2MZFZAeW
|
||||
zeBQFCfb103lvYeWGxU9BlhNAP49Ce/Y8SsokcQwmsR8datld+Pe/QmF4/zQl2+R
|
||||
D30tB7g4BGBR3XISCisGAQQBl1UBBQEBB0DOngNGofghQ3QrqoO/WUJ958cJMGmE
|
||||
wInz5Gfiby0BOAMBCAeIdQQYFgoAHQUCYFHdcgIbDAUWAgMBAAQLCQgHBRUKCQgL
|
||||
Ah4BAAoJEMrL/Yggs1365w0A/26IRKTvZpcIGIypXY5B9v5MySrCJJeMFaBTZ2oP
|
||||
q0MDAP9vWnMlAbAGkdRqbw6uA+rKuTyTnOR7sIroMWQXOy9pBw==
|
||||
=5H8m
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: PGPainless
|
||||
|
||||
mDMEYFHdchYJKwYBBAHaRw8BAQdA8RbR/TCSQTRszBfELI+TckBaXusWSzQWmJ+A
|
||||
m6R2vdO0E2ZyZXNoQGVuY3J5cHRlZC5rZXmIeAQTFgoAIAUCYFHdcgIbAwUWAgMB
|
||||
AAQLCQgHBRUKCQgLAh4BAhkBAAoJECFoxR5ec+rpzCsBAOPe/5BHmPuS6lRDPFK2
|
||||
Ww2lgEaCo0z88mLKp2DTzzwlAQDlnlrUpA0huJLmI0qqAi+eH0bgUwciqmsC7/4d
|
||||
6/6sCbg4BGBR3XISCisGAQQBl1UBBQEBB0ASLlXkJvhzAihOff7OLGQNlyD/+lCQ
|
||||
1/qu/Ojr5GVbCwMBCAeIdQQYFgoAHQUCYFHdcgIbDAUWAgMBAAQLCQgHBRUKCQgL
|
||||
Ah4BAAoJECFoxR5ec+rptOcA/iBkqa5nJNM03BDEyBaz87Ez28K5L8vltRwBUE/+
|
||||
LIrJAP43S3skfM1ErB/BPFv9YJzoTVaY5vESyEYoB6sw1H4iCA==
|
||||
=wnXr
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: PGPainless
|
||||
|
||||
mDMEYFHdchYJKwYBBAHaRw8BAQdA7qoKX7JDTjgbrnFKLfb43veznuC7z4KJ7acI
|
||||
dXZI2om0E2ZyZXNoQGVuY3J5cHRlZC5rZXmIeAQTFgoAIAUCYFHdcgIbAwUWAgMB
|
||||
AAQLCQgHBRUKCQgLAh4BAhkBAAoJEON4/e8A5cOx9c0BAPtneXwDhnhrtqG7JSue
|
||||
0youMdGRCzKd8mfAkao/JAu+AP9TKRY6aqLQtwWUEhAUfE6TEic3x+WRlYAGBp7I
|
||||
5XPpDLg4BGBR3XISCisGAQQBl1UBBQEBB0DSEcmogCWdMfhfmq7MlWuuzj9BuJo+
|
||||
qdrEvcSyAOolaAMBCAeIdQQYFgoAHQUCYFHdcgIbDAUWAgMBAAQLCQgHBRUKCQgL
|
||||
Ah4BAAoJEON4/e8A5cOxpusA/iyib7m5aFuStRWlBs9MYfmEv3vbDGrDZoN+6wj0
|
||||
U3y7AQDskovK4Wd/vf2ljUOxP6knS01zriQpHy9ro5Qgi8bTCQ==
|
||||
=p/wh
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
Loading…
Reference in a new issue