WebOfTrustInfo / ld-signatures-java

Java implementation of Linked Data Signatures
Apache License 2.0
16 stars 15 forks source link

How to create a ByteVerifier within a JsonWebSignature2020LdVerifier? #17

Closed 8sd closed 1 year ago

8sd commented 1 year ago

Hi,

I'm currently developing the validation of a Linked Data Proof. I followed the development examples to implement the code:

VerifiablePresentation presentation = VerifiablePresentation.fromJson(json);
LdVerifier verifier = new JsonWebSignature2020LdVerifier();
verifier.verify(presentation);

Unfortunately, the function verify throws a NullPointerException when getting the Algorithm from the verifier.

I would have thought that the suiting verifier is chosen automatically depending on the to-be-verified JWS. Now I'm trying to generate the verifier manually. However, I fail to do it. I fail somewhere in generating the RSA Keys manually. Also, it doesn't feel like doing it correctly since the algorithm might change in different JWSs.

Do I miss something here? How can this issue be resolved?

I really appreciate any help you can provide. Sebastian

peacekeeper commented 1 year ago

Hello @8sd thanks for your question. Would you mind posting here the value of the "json" variable, i.e. the VP you are trying to verify?

Also, can you explain why you are trying to generate RSA keys, if you are only trying to verify something?

8sd commented 1 year ago

Hello @peacekeeper, thanks for reaching out.

I sent you the JSON via mail since I'm not sure if I'm allowed to share it publicly.

I don't try to create RSA keys. The RSA keys should be determined by the verificationMethod. However, since JsonWebSignature2020LdVerifier doesn't do it, I tried to create the RSA public key object manually.

peacekeeper commented 1 year ago

Okay, so you have to construct an instance of a ByteVerifier, otherwise the JsonWebSignature2020LdVerifier wouldn't know which public key to use for the verification.

I assume you have the corresponding public key somewhere, maybe in JWK format?

In that case, one way how you can construct the ByteVerifier is like this:

JWK jwk = JWK.fromJson(jwkJson);
PublicKeyVerifier<?> publicKeyVerifier = PublicKeyVerifierFactory.publicKeyVerifierForKey(
    KeyTypeName_for_JWK.keyTypeName_for_JWK(jwk),
    JWSAlgorithm.PS256,
    JWK_to_PublicKey.JWK_to_anyPublicKey(jwk));

You can then initialize the JsonWebSignature2020LdVerifier as follows:

LdVerifier verifier = new JsonWebSignature2020LdVerifier(publicKeyVerifier);

I just pushed a commit to key-formats-java with a convenience method that should make this a bit easier: https://github.com/danubetech/key-formats-java/commit/0b515d1452b0786226cac6fa98832bbf10bac6b7

Does this help?

8sd commented 1 year ago

Yes, this helps very much!

Thanks. I was unaware that I must build the PublicKeyVerifier manually, but your snipped helped.

8sd commented 1 year ago

Since the verification is working now, I want to sign VCs and VPs. So far, I came up with the following code:

VerifiableCredential vc = VerifiableCredential.fromJson(<string>);

        PrivateKeySigner pkSigner = new PrivateKeySigner;
        LdSigner signer = new JsonWebSignature2020LdSigner(pkSigner);

        signer.setCreated(new Date());
        signer.setProofPurpose(LDSecurityKeywords.JSONLD_TERM_ASSERTIONMETHOD);
        signer.setVerificationMethod(URI.create("did:web:..."));

        LdProof ldProof = signer.sign(vc);

Now I'm asking myself how to create the ByteSigner pkSigner. Do you have an example, of how to do this based on an x509 certificate?

Thanks in advance!

peacekeeper commented 1 year ago

Hello again.. If you have the private key in JWK form, then this should work in a similar way as before, e.g.:

        PrivateKeySigner<?> privateKeySigner = PrivateKeySignerFactory.privateKeySignerForKey(
                KeyTypeName_for_JWK.keyTypeName_for_JWK(jwk),
                JWSAlgorithm.PS256,
                JWK_to_PrivateKey.JWK_to_anyPrivateKey(jwk));

If you have an instance of java.security.KeyPair, you could do it like this:

        PrivateKeySigner<?> privateKeySigner = new RSA_PS256_PrivateKeySigner(keyPair);

Does this help?

8sd commented 1 year ago

Hi peacekeeper,

thanks for your answer. I think it helped.

When I'm signing and verifying VPs/VCs with your library, are they normalized using URDNA2015? If not, how are they normalized? And would it be possible to use URDNA2015?

Thanks in advance.

peacekeeper commented 1 year ago

Yes, URDNA2015 is used for most of the signature suites (e.g. Ed25519Signature2020LdSigner, EcdsaSecp256k1Signature2019LdSigner, etc.)

Some of the signature suites use JCS instead (e.g. JcsEd25519Signature2020LdSigner, etc.)

8sd commented 1 year ago

Now, the code works. Thanks for your awesome help! 👍