2022-03-02 17:01:30 +01:00
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.wkd.test_suite ;
2022-03-21 13:11:00 +01:00
import org.bouncycastle.openpgp.PGPPublicKey ;
import org.bouncycastle.openpgp.PGPPublicKeyRing ;
import org.bouncycastle.openpgp.PGPSecretKeyRing ;
import org.bouncycastle.openpgp.PGPSignature ;
import org.pgpainless.PGPainless ;
import org.pgpainless.key.protection.SecretKeyRingProtector ;
import pgp.wkd.discovery.DiscoveryMethod ;
2022-03-02 17:01:30 +01:00
import java.io.File ;
import java.io.IOException ;
2022-03-13 16:08:04 +01:00
import java.io.OutputStream ;
2022-03-02 17:01:30 +01:00
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Iterator ;
import java.util.List ;
2022-03-13 16:08:04 +01:00
import java.util.Random ;
2022-04-02 17:23:55 +02:00
public class TestSuiteGenerator extends AbstractTestSuiteGenerator {
2022-03-02 17:01:30 +01:00
public TestSuiteGenerator ( String domain ) {
2022-04-02 17:23:55 +02:00
super ( domain ) ;
2022-03-02 17:01:30 +01:00
}
2022-03-19 14:08:35 +01:00
public TestSuite generateTestSuiteInDirectory ( File directory , DiscoveryMethod method ) throws Exception {
WkdDirectoryStructure dirs = directoryStructureForMethod ( directory , method ) ;
dirs . mkdirs ( ) ;
2022-03-02 17:01:30 +01:00
List < TestCase > tests = new ArrayList < > ( ) ;
2022-03-19 14:08:35 +01:00
tests . add ( test_baseCase ( dirs ) ) ;
tests . add ( test_baseCaseMultipleCertificates ( dirs ) ) ;
tests . add ( test_wrongUserId ( dirs ) ) ;
tests . add ( test_noUserId ( dirs ) ) ;
tests . add ( test_unboundUserId ( dirs ) ) ;
tests . addAll ( test_baseCaseMultiUserIds ( dirs ) ) ;
tests . add ( test_secretKeyMaterial ( dirs ) ) ;
tests . add ( test_randomBytes ( dirs ) ) ;
2022-03-21 13:11:00 +01:00
tests . add ( test_missingCertificate ( dirs ) ) ;
2022-03-02 17:01:30 +01:00
return new TestSuite ( " 0.1 " , tests ) ;
}
2022-03-19 14:08:35 +01:00
// TEST CASES
2022-03-02 17:01:30 +01:00
2022-03-19 14:08:35 +01:00
private TestCase test_baseCase ( WkdDirectoryStructure directoryStructure ) throws Exception {
2022-03-02 17:01:30 +01:00
String lookupMail = " base-case@ " + domain ;
String userId = " WKD-Test Base Case <base-case@ " + domain + " > " ;
String description = " Certificate has a single, valid user-id ' " + userId + " ' " ;
PGPPublicKeyRing publicKeys = certificate ( userId ) ;
2022-03-13 16:08:04 +01:00
writeDataFor ( lookupMail , directoryStructure , new DataSink ( ) {
@Override
public void write ( OutputStream outputStream ) throws IOException {
publicKeys . encode ( outputStream ) ;
}
} ) ;
2022-03-02 17:01:30 +01:00
2022-03-19 14:08:35 +01:00
return TestCase . ok ( " Base Case " , description , lookupMail , directoryStructure ) ;
2022-03-02 17:01:30 +01:00
}
2022-03-19 14:08:35 +01:00
private List < TestCase > test_baseCaseMultiUserIds ( WkdDirectoryStructure directoryStructure ) throws Exception {
2022-03-02 17:01:30 +01:00
String primaryLookupMail = " primary-uid@ " + domain ;
String secondaryLookupMail = " secondary-uid@ " + domain ;
String primaryUserId = " WKD-Test Primary User-ID < " + primaryLookupMail + " > " ;
String secondaryUserId = " WKD-Test Secondary User-ID < " + secondaryLookupMail + " > " ;
String primaryDescription = " Certificate has multiple, valid user-ids. Is looked up via primary user-id ' " + primaryUserId + " ' using mail address ' " + primaryLookupMail + " '. " ;
String secondaryDescription = " Certificate has multiple, valid user-ids. Is looked up via secondary user-id ' " + secondaryUserId + " ' using mail address ' " + secondaryLookupMail + " '. " ;
2022-04-02 17:23:55 +02:00
PGPSecretKeyRing secretKeys = secretKey ( primaryUserId ) ;
2022-03-02 17:01:30 +01:00
SecretKeyRingProtector protector = SecretKeyRingProtector . unprotectedKeys ( ) ;
secretKeys = PGPainless . modifyKeyRing ( secretKeys )
. addUserId ( secondaryUserId , protector )
. done ( ) ;
PGPPublicKeyRing publicKeys = PGPainless . extractCertificate ( secretKeys ) ;
2022-03-13 16:08:04 +01:00
DataSink sink = new DataSink ( ) {
@Override
public void write ( OutputStream outputStream ) throws IOException {
publicKeys . encode ( outputStream ) ;
}
} ;
2022-03-02 17:01:30 +01:00
2022-03-13 16:08:04 +01:00
writeDataFor ( primaryLookupMail , directoryStructure , sink ) ;
writeDataFor ( secondaryLookupMail , directoryStructure , sink ) ;
2022-03-02 17:01:30 +01:00
return Arrays . asList (
2022-03-13 16:08:04 +01:00
TestCase . ok ( " Multi-User-ID - Primary User-ID Lookup " ,
primaryDescription , primaryLookupMail , directoryStructure ) ,
TestCase . ok ( " Multi-User-ID - Secondary User-ID Lookup " ,
secondaryDescription , secondaryLookupMail , directoryStructure )
2022-03-02 17:01:30 +01:00
) ;
}
2022-03-19 14:08:35 +01:00
private TestCase test_baseCaseMultipleCertificates ( WkdDirectoryStructure directoryStructure ) throws Exception {
2022-03-13 16:08:04 +01:00
String title = " Multiple Certificates " ;
String description = " The result contains multiple certificates. " ;
String lookupMail = " multiple-certificates@ " + domain ;
String userId1 = " First Certificate < " + lookupMail + " > " ;
String userId2 = " Second Certificate < " + lookupMail + " > " ;
PGPPublicKeyRing cert1 = certificate ( userId1 ) ;
PGPPublicKeyRing cert2 = certificate ( userId2 ) ;
writeDataFor ( lookupMail , directoryStructure , new DataSink ( ) {
@Override
public void write ( OutputStream outputStream ) throws IOException {
cert1 . encode ( outputStream ) ;
cert2 . encode ( outputStream ) ;
}
} ) ;
return TestCase . ok ( title , description , lookupMail , directoryStructure ) ;
}
2022-03-19 14:08:35 +01:00
private TestCase test_wrongUserId ( WkdDirectoryStructure directoryStructure ) throws Exception {
2022-03-02 17:01:30 +01:00
String lookupMail = " wrong-userid@ " + domain ;
String userId = " WKD-Test Different User-ID <different-userid@ " + domain + " > " ;
String description = " Certificate has a single, valid user-id ' " + userId + " ', but is deposited for mail address ' " + lookupMail + " '. " ;
PGPPublicKeyRing publicKeys = certificate ( userId ) ;
2022-03-13 16:08:04 +01:00
writeDataFor ( lookupMail , directoryStructure , new DataSink ( ) {
@Override
public void write ( OutputStream outputStream ) throws IOException {
publicKeys . encode ( outputStream ) ;
}
} ) ;
2022-03-02 17:01:30 +01:00
2022-03-13 16:08:04 +01:00
return TestCase . fail ( " Wrong User-ID " , description , lookupMail , directoryStructure ) ;
2022-03-02 17:01:30 +01:00
}
2022-03-19 14:08:35 +01:00
private TestCase test_unboundUserId ( WkdDirectoryStructure directoryStructure ) throws Exception {
2022-03-13 16:53:22 +01:00
String lookupMail = " unbound-userid@ " + domain ;
String userId = " WKD-Test Unbound User-ID < " + lookupMail + " > " ;
String description = " Certificate has a single User-ID ' " + userId + " ' without binding signature. " ;
PGPPublicKeyRing publicKeys = certificate ( userId ) ;
Iterator < PGPPublicKey > keyIterator = publicKeys . iterator ( ) ;
PGPPublicKey primaryKey = keyIterator . next ( ) ;
Iterator < PGPSignature > bindingSigs = primaryKey . getSignaturesForID ( userId ) ;
while ( bindingSigs . hasNext ( ) ) {
primaryKey = PGPPublicKey . removeCertification ( primaryKey , userId , bindingSigs . next ( ) ) ;
}
List < PGPPublicKey > keys = new ArrayList < > ( ) ;
keys . add ( primaryKey ) ;
while ( keyIterator . hasNext ( ) ) {
keys . add ( keyIterator . next ( ) ) ;
}
PGPPublicKeyRing certificateWithoutUserIdBinding = new PGPPublicKeyRing ( keys ) ;
writeDataFor ( lookupMail , directoryStructure , new DataSink ( ) {
@Override
public void write ( OutputStream outputStream ) throws IOException {
certificateWithoutUserIdBinding . encode ( outputStream ) ;
}
} ) ;
return TestCase . fail ( " Unbound UserId " , description , lookupMail , directoryStructure ) ;
}
2022-03-19 14:08:35 +01:00
private TestCase test_noUserId ( WkdDirectoryStructure directoryStructure ) throws Exception {
2022-03-02 17:01:30 +01:00
String lookupMail = " absent-userid@ " + domain ;
String description = " Certificate has no user-id, but is deposited for mail address ' " + lookupMail + " '. " ;
// Generate certificate with temp user-id
PGPPublicKeyRing publicKeys = certificate ( " DeleteMe " ) ;
// delete user-id
List < PGPPublicKey > keys = new ArrayList < > ( ) ;
Iterator < PGPPublicKey > publicKeyIterator = publicKeys . iterator ( ) ;
PGPPublicKey primaryKey = publicKeyIterator . next ( ) ;
primaryKey = PGPPublicKey . removeCertification ( primaryKey , " DeleteMe " ) ;
keys . add ( primaryKey ) ;
while ( publicKeyIterator . hasNext ( ) ) {
keys . add ( publicKeyIterator . next ( ) ) ;
}
publicKeys = new PGPPublicKeyRing ( keys ) ;
2022-03-13 16:08:04 +01:00
PGPPublicKeyRing finalPublicKeys = publicKeys ;
writeDataFor ( lookupMail , directoryStructure , new DataSink ( ) {
@Override
public void write ( OutputStream outputStream ) throws IOException {
finalPublicKeys . encode ( outputStream ) ;
}
} ) ;
2022-03-02 17:01:30 +01:00
2022-03-13 16:08:04 +01:00
return TestCase . fail ( " No User-ID " , description , lookupMail , directoryStructure ) ;
2022-03-02 17:01:30 +01:00
}
2022-03-19 14:08:35 +01:00
private TestCase test_secretKeyMaterial ( WkdDirectoryStructure directoryStructure ) throws Exception {
2022-03-02 17:01:30 +01:00
String lookupMail = " test-secret-key@ " + domain ;
String description = " Certificate file contains secret key material. " ;
2022-03-19 14:08:35 +01:00
PGPSecretKeyRing secretKeys = secretKey ( " WKD-Test Secret Key < " + lookupMail + " > " ) ;
2022-03-02 17:01:30 +01:00
2022-03-13 16:08:04 +01:00
writeDataFor ( lookupMail , directoryStructure , new DataSink ( ) {
@Override
public void write ( OutputStream outputStream ) throws IOException {
secretKeys . encode ( outputStream ) ;
}
} ) ;
return TestCase . fail ( " Secret Key Material " , description , lookupMail , directoryStructure ) ;
}
2022-03-19 14:08:35 +01:00
private TestCase test_randomBytes ( WkdDirectoryStructure directoryStructure )
throws IOException {
2022-03-13 16:08:04 +01:00
String lookupMail = " random-bytes@ " + domain ;
String description = " Certificate file contains random bytes. " ;
Random random = new Random ( ) ; // No need for Secure Random here
writeDataFor ( lookupMail , directoryStructure , outputStream - > {
byte [ ] buf = new byte [ random . nextInt ( 65536 ) ] ;
random . nextBytes ( buf ) ;
outputStream . write ( buf ) ;
} ) ;
return TestCase . fail ( " Random Bytes " , description , lookupMail , directoryStructure ) ;
}
2022-03-21 13:11:00 +01:00
private TestCase test_missingCertificate ( WkdDirectoryStructure dirs ) {
String lookupMail = " missing-cert@ " + domain ;
String title = " Missing certificate " ;
String description = " There is no certificate for the lookup mail address ' " + lookupMail + " '. " ;
return TestCase . fail ( title , description , lookupMail , dirs ) ;
}
2022-03-02 17:01:30 +01:00
}