Use case: thousands of users, get user by signature

15 views
Skip to first unread message

Stephen Beitzel

unread,
Mar 28, 2018, 10:31:06 PM3/28/18
to DidiSoft Forum
I'm writing an application which accepts (via HTTP POST or by email) encrypted and signed messages. There are, potentially, thousands of users. Rather than have a single KeyStore containing every single user's key (with the associated concurrency problems) I've stored each user's public key off in a database along with the rest of their user profile. It seems to me that it ought to be possible to decrypt the incoming message (since it's encrypted to the application's key) and then inspect the signature to get the signing key's ID, which I could use to look up the user (and then fetch the user's key and verify the message). However, the methods on PGPInspectLib and PGPLib don't seem to be supporting this use case.

For example:

public static PlayerDataObject findSigningPlayer(String signedMessage) throws InternalException, IllegalArgumentException, NotFoundException {
   
try {
       
ByteArrayInputStream bis = new ByteArrayInputStream(signedMessage.getBytes("ASCII"));
       
PGPInspectLib inspect = new PGPInspectLib();
       
PGPLib pgp = new PGPLib();
       
ByteArrayInputStream serverKeyStream = new ByteArrayInputStream(CryptoManager.getInstance().getMyPublicKey().getBytes("ASCII"));
       
String serverKeyPass = CryptoManager.getInstance().getSecretKeyPass();
       
List<PlayerDataObject> potentials = new ArrayList<>();
       
boolean isSignedOnly = inspect.isSignedOnly(bis);
        bis
.reset();
       
if (isSignedOnly) {
           
long[] signingKeyIds = inspect.listSigningKeyIds(bis);
            bis
.reset();
           
for (long keyID : signingKeyIds) {
               
try {
                    potentials
.addAll(PlayerDataObject.lookupByKeyID(keyID));
               
} catch (Exception e) {
                   
__l.warn("Problem looking up player for key {}", Long.valueOf(keyID));
               
}
           
}
       
} else {
           
// assume it's signed and encrypted
            // This call throws a PGPException, claiming that the library couldn't find the key to decrypt the message. However, GPG is able to decrypt it just fine.
           
SignatureItem[] signatures = inspect.listSignatures(bis, serverKeyStream, serverKeyPass);
            bis
.reset();
            serverKeyStream
.reset();
           
for (SignatureItem item : signatures) {
               
long keyID = item.getKeyId();
               
try {
                    potentials
.addAll(PlayerDataObject.lookupByKeyID(keyID));
               
} catch (Exception e) {
                   
__l.warn("Problem looking up player for key {}", Long.valueOf(keyID));
               
}
           
}
       
}
       
// now, we have a list of potential players
        for (PlayerDataObject pdo : potentials) {
           
// see if the player's key is the one that signed the message
            KeyStore playerKey = new KeyStore();
           
ByteArrayInputStream playerKeyStream = new ByteArrayInputStream(pdo.getPublicKey().getBytes("ASCII"));
            playerKey
.loadFromStream(playerKeyStream);
            playerKeyStream
.reset();
           
if (isSignedOnly) {
               
SignatureCheckResult result = pgp.verifyWithoutExtracting(bis, playerKey);
                bis
.reset();
               
if (result == SignatureVerified) {
                   
return pdo;
               
}
           
} else {
               
ByteArrayOutputStream baos = new ByteArrayOutputStream();
               
SignatureCheckResult result = pgp.decryptAndVerify(bis, serverKeyStream, serverKeyPass, playerKeyStream, baos);
                bis
.reset();
                serverKeyStream
.reset();
               
if (result == SignatureVerified) {
                   
return pdo;
               
}
           
}
       
}
   
} catch (UnsupportedEncodingException uee) {
       
__l.error("Check JVM - ASCII isn't supported", uee);
       
throw new InternalException("Unsupported encoding; check JVM installation", uee);
   
} catch (IOException ioe) {
       
__l.error("Exception reading memory!", ioe);
       
throw new InternalException("Unable to read from memory", ioe);
   
} catch (PGPException pe) {
       
__l.error("signed data is malformed", pe);
       
throw new IllegalArgumentException("Malformed data provided", pe);
   
}
   
throw new NotFoundException("No qualifying player key found");
}


DidiSoft Support

unread,
Mar 29, 2018, 8:14:15 AM3/29/18
to didisof...@googlegroups.com, Stephen Beitzel
Hi Stephen,

The method call

SignatureItem[] signatures = inspect.listSignatures(bis, serverKeyStream, serverKeyPass);


expects the private key of the player (
in the serverKeyStream variable
) in order to decrypt the message and return back the list of signatures
. I guess that you have received WrongPrivateKeyException at that line !! The correct way to get the encrypting key(s) ID(s) is with PGPInspectLib.listEncryptionKeyIds(String). Please let me know if you need further assistance how to implement this use case.

Kind Regards
Peter Kalef
Technical Support

--
You received this message because you are subscribed to the Google Groups "DidiSoft Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to didisoft_foru...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages