All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.DNAProject.dnaid.jwt.JWTCredential Maven / Gradle / Ivy

package com.github.DNAProject.dnaid.jwt;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONType;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.github.DNAProject.account.Account;
import com.github.DNAProject.dnaid.Proof;
import com.github.DNAProject.dnaid.VerifiableCredential;
import com.github.DNAProject.dnaid.VerifiablePresentation;
import com.github.DNAProject.sdk.exception.SDKException;

import java.util.Base64;

@JSONType(orders = {"header", "payload", "jws"})
public class JWTCredential {
    public String jws;
    public JWTHeader header;
    public JWTPayload payload;

    public JWTCredential() {
    }

    // payload.jti need to be recalculated
    // jti should be uuid, not json-ld hash
    public JWTCredential(JWTHeader header, JWTPayload payload, Account signer) throws Exception {
        this.header = header;
        this.payload = payload;
        byte[] needSignData = this.genNeedSignData();
        byte[] sig = signer.generateSignature(needSignData, signer.getSignatureScheme(), null);
        jws = Base64.getEncoder().encodeToString(sig);
    }

    private JWTCredential(String header, String payload, String jws) {
        this.jws = jws;
        Base64.Decoder decoder = Base64.getDecoder();
        byte[] decodedHeader = decoder.decode(header);
        byte[] decodedPayload = decoder.decode(payload);
        this.header = JSON.parseObject(decodedHeader, JWTHeader.class);
        // should parse iss and credentialSubject by field order
        this.payload = JSON.parseObject(decodedPayload, JWTPayload.class, Feature.OrderedField);
    }

    // the proof signature should be jws
    public JWTCredential(VerifiableCredential credential) throws Exception {
        if (credential.proof == null) {
            throw new SDKException("proof is null");
        }
        if (credential.proof.jws == null || credential.proof.jws.isEmpty()) {
            throw new SDKException("credential has no jws");
        }
        this.header = new JWTHeader(credential);
        this.payload = new JWTPayload(credential);
        this.jws = credential.proof.jws;
    }

    // the proof signature should be jws
    public JWTCredential(VerifiablePresentation presentation, Proof proof) throws Exception {
        if (proof == null) {
            throw new SDKException("proof is null");
        }
        if (proof.jws == null || proof.jws.isEmpty()) {
            throw new SDKException("credential has no jws");
        }
        this.jws = proof.jws;
        this.header = new JWTHeader(proof);
        this.payload = new JWTPayload(presentation, proof);
    }

    public static JWTCredential deserializeToJWTCred(String jwt) throws Exception {
        String[] parts = jwt.split("\\.");
        if (parts.length != 3) {
            throw new SDKException("invalid jwt cred");
        }
        return new JWTCredential(parts[0], parts[1], parts[2]);
    }

    public byte[] genNeedSignData() {
        String header = Base64.getEncoder().encodeToString(
                JSON.toJSONString(this.header, SerializerFeature.MapSortField).getBytes());
        String payload = Base64.getEncoder().encodeToString(
                JSON.toJSONString(this.payload, SerializerFeature.MapSortField).getBytes());
        String needSignData = header + "." + payload;
        return needSignData.getBytes();
    }

    public Proof parseProof() {
        Proof p = null;
        if (this.payload.vc != null) {
            p = this.payload.vc.proof;
        } else if (this.payload.vp != null) {
            p = this.payload.vp.proof;
        }
        Proof proof = new Proof();
        if (p != null) {
            proof.proofPurpose = p.proofPurpose;
            proof.hex = p.hex;
            proof.created = p.created;
        }
        proof.type = this.header.alg.proofPubKeyType();
        proof.verificationMethod = this.header.kid;
        proof.jws = this.jws;
        proof.domain = this.payload.aud;
        proof.challenge = this.payload.nonce;
        return proof;
    }

    public byte[] parseSignature() {
        return Base64.getDecoder().decode(this.jws);
    }

    @Override
    public String toString() {
        String header = Base64.getEncoder().encodeToString(
                JSON.toJSONString(this.header, SerializerFeature.MapSortField).getBytes());
        String payload = Base64.getEncoder().encodeToString(
                JSON.toJSONString(this.payload, SerializerFeature.MapSortField).getBytes());
        return header + "." + payload + "." + jws;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy