Skip to content

Commit

Permalink
feat: add extra transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
andreibogus authored and aleksandra-bel committed Mar 15, 2024
1 parent 8ddaa84 commit b694d19
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,35 @@
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.crypto.ECDSASigner;
import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.ECKey;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.gen.ECKeyGenerator;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;
import org.eclipse.tractusx.managedidentitywallets.constant.SupportedAlgorithms;
import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet;
import org.eclipse.tractusx.managedidentitywallets.dao.entity.WalletKey;
import org.eclipse.tractusx.managedidentitywallets.dao.repository.WalletRepository;
import org.eclipse.tractusx.managedidentitywallets.exception.BadDataException;
import org.eclipse.tractusx.managedidentitywallets.exception.SignatureFailureException;
import org.eclipse.tractusx.managedidentitywallets.exception.UnsupportedAlgorithmException;
import org.eclipse.tractusx.managedidentitywallets.utils.EncryptionUtils;
import org.eclipse.tractusx.ssi.lib.model.did.Did;
import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential;
import org.eclipse.tractusx.ssi.lib.model.verifiable.presentation.VerifiablePresentation;
import org.eclipse.tractusx.ssi.lib.model.verifiable.presentation.VerifiablePresentationBuilder;
import org.eclipse.tractusx.ssi.lib.serialization.jsonLd.JsonLdSerializer;
import org.eclipse.tractusx.ssi.lib.serialization.jwt.SerializedVerifiablePresentation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.StringWriter;
import java.net.URI;
import java.security.interfaces.ECPrivateKey;
import java.util.Date;
Expand All @@ -52,11 +67,22 @@
import java.util.UUID;
import java.util.stream.Collectors;

@RequiredArgsConstructor

@Service
public class JwtPresentationES256KService {

private final JsonLdSerializer jsonLdSerializer;
private final Did agentDid;
private JsonLdSerializer jsonLdSerializer;
private Did agentDid;
private WalletRepository walletRepository;
private EncryptionUtils encryptionUtils;
private WalletKeyService walletKeyService;

@Autowired
public JwtPresentationES256KService(WalletRepository walletRepository, EncryptionUtils encryptionUtils, WalletKeyService walletKeyService) {
this.walletRepository = walletRepository;
this.encryptionUtils = encryptionUtils;
this.walletKeyService = walletKeyService;
}

public JwtPresentationES256KService(Did agentDid, JsonLdSerializer jsonLdSerializer) {
this.agentDid = agentDid;
Expand All @@ -76,6 +102,54 @@ public SignedJWT createPresentation(Did issuer, List<VerifiableCredential> crede
return createSignedJwt(verifiablePresentation.getId(), issuer, audience, serializedVerifiablePresentation, ecPrivateKey);
}

public void storeWalletKeyES256K(Wallet wallet) {
WalletKey walletKeyES256K;
try {
// create additional key pair ES256K
ECKey ecJwk = new ECKeyGenerator(Curve.SECP256K1)
.keyUse(KeyUse.SIGNATURE)
.keyID(UUID.randomUUID().toString())
.provider(BouncyCastleProviderSingleton.getInstance())
.generate();

Wallet walletFromDB = walletRepository.getByDid(wallet.getDid());
walletKeyES256K = WalletKey.builder()
.wallet(walletFromDB)
.keyId(UUID.randomUUID().toString())
.referenceKey("dummy ref key, removed once vault setup is ready")
.vaultAccessToken("dummy vault access token, removed once vault setup is ready")
.privateKey(encryptionUtils.encrypt(getPrivateKeyString(ecJwk.toECPrivateKey().getEncoded())))
.publicKey(encryptionUtils.encrypt(getPublicKeyString(ecJwk.toECPublicKey().getEncoded())))
.algorithm(SupportedAlgorithms.ES256K.toString())
.build();
} catch (JOSEException e) {
throw new BadDataException("Could not generate EC Jwk", e);
}

//Save key ES256K
walletKeyService.getRepository().save(walletKeyES256K);
}

@SneakyThrows
private String getPrivateKeyString(byte[] privateKeyBytes) {
StringWriter stringWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(stringWriter);
pemWriter.writeObject(new PemObject("PRIVATE KEY", privateKeyBytes));
pemWriter.flush();
pemWriter.close();
return stringWriter.toString();
}

@SneakyThrows
private String getPublicKeyString(byte[] publicKeyBytes) {
StringWriter stringWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(stringWriter);
pemWriter.writeObject(new PemObject("PUBLIC KEY", publicKeyBytes));
pemWriter.flush();
pemWriter.close();
return stringWriter.toString();
}

public SignedJWT createSignedJwt(URI id, Did didIssuer, String audience, SerializedVerifiablePresentation serializedPresentation, ECPrivateKey ecPrivateKey) {
String issuer = didIssuer.toString();
String subject = didIssuer.toString();
Expand All @@ -90,8 +164,7 @@ public SignedJWT createSignedJwt(URI id, Did didIssuer, String audience, Seriali
.jwtID(id.toString())
.build();
return createSignedES256KJwt(ecPrivateKey, claimsSet, issuer);
}
catch (IOException e) {
} catch (IOException e) {
throw new BadDataException("Incorrect VP serialization");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,9 @@ private void buildVPJwtEdDSA(String audience, String callerBpn, Wallet callerWal

private void buildVPJwtES256K(String audience, String callerBpn, Wallet callerWallet, List<VerifiableCredential> verifiableCredentials, SupportedAlgorithms algorithm, Map<String, Object> response) {
Pair<Did, Object> result = getPrivateKey(callerWallet, algorithm, audience, callerBpn);
ECPrivateKey ecPrivateKey = (ECPrivateKey) result;
ECPrivateKey ecPrivateKey = (ECPrivateKey) result.getRight();

JwtPresentationES256KService presentationFactory = new JwtPresentationES256KService(new JsonLdSerializerImpl(), result.getLeft());
JwtPresentationES256KService presentationFactory = new JwtPresentationES256KService(result.getLeft(), new JsonLdSerializerImpl());
SignedJWT presentation;
presentation = presentationFactory.createPresentation(result.getLeft()
, verifiableCredentials, audience, ecPrivateKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@

package org.eclipse.tractusx.managedidentitywallets.service;

import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.ECKey;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.gen.ECKeyGenerator;
import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton;
import com.smartsensesolutions.java.commons.FilterRequest;
import com.smartsensesolutions.java.commons.base.repository.BaseRepository;
import com.smartsensesolutions.java.commons.base.service.BaseService;
Expand Down Expand Up @@ -66,9 +61,6 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

Expand Down Expand Up @@ -111,6 +103,8 @@ public class WalletService extends BaseService<Wallet, Long> {
@Qualifier("transactionManager")
private final PlatformTransactionManager transactionManager;

private final JwtPresentationES256KService jwtPresentationES256KService;


@Override
protected BaseRepository<Wallet, Long> getRepository() {
Expand Down Expand Up @@ -213,9 +207,27 @@ public Page<Wallet> getWallets(int pageNumber, int size, String sortColumn, Stri
* @return the wallet
*/
@SneakyThrows
@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation = Propagation.REQUIRED)
public Wallet createWallet(CreateWalletRequest request, String callerBpn) {
return createWallet(request, false, callerBpn);
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.setPropagationBehavior(0);
transactionTemplate.setIsolationLevel(1);

final Wallet[] wallets = new Wallet[1];
transactionTemplate.execute(new TransactionCallbackWithoutResult(){
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
wallets[0] = createWallet(request, false, callerBpn);
}
});

transactionTemplate.execute(new TransactionCallbackWithoutResult(){
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
jwtPresentationES256KService.storeWalletKeyES256K(wallets[0]);
}
});

return wallets[0];
}

/**
Expand All @@ -231,12 +243,6 @@ private Wallet createWallet(CreateWalletRequest request, boolean authority, Stri
//create private key pair EdDSA
IKeyGenerator keyGenerator = new x21559Generator();
KeyPair keyPair = keyGenerator.generateKey();
// create additional key pair ES256K
ECKey ecJwk = new ECKeyGenerator(Curve.SECP256K1)
.keyUse(KeyUse.SIGNATURE)
.keyID(UUID.randomUUID().toString())
.provider(BouncyCastleProviderSingleton.getInstance())
.generate();

//create did json
Did did = DidWebFactory.fromHostnameAndPath(miwSettings.host(), request.getBpn());
Expand Down Expand Up @@ -286,19 +292,6 @@ private Wallet createWallet(CreateWalletRequest request, boolean authority, Stri
walletKeyService.getRepository().save(walletKeyED25519);
log.debug("Wallet created for bpn ->{}", StringEscapeUtils.escapeJava(request.getBpn()));

WalletKey walletKeyES256K = WalletKey.builder()
.wallet(wallet)
.keyId(UUID.randomUUID().toString())
.referenceKey("dummy ref key, removed once vault setup is ready")
.vaultAccessToken("dummy vault access token, removed once vault setup is ready")
.privateKey(encryptionUtils.encrypt(getPrivateKeyString(ecJwk.toECPrivateKey().getEncoded())))
.publicKey(encryptionUtils.encrypt(getPublicKeyString(ecJwk.toECPublicKey().getEncoded())))
.algorithm(SupportedAlgorithms.ES256K.toString())
.build();

//Save key ES256K
walletKeyService.getRepository().save(walletKeyES256K);

Wallet issuerWallet = walletRepository.getByBpn(miwSettings.authorityWalletBpn());

//issue BPN credentials
Expand All @@ -313,6 +306,7 @@ private Wallet createWallet(CreateWalletRequest request, boolean authority, Stri
@PostConstruct
public void createAuthorityWallet() {
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
final Wallet[] wallet = new Wallet[1];
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
Expand All @@ -321,13 +315,22 @@ protected void doInTransactionWithoutResult(TransactionStatus status) {
.name(miwSettings.authorityWalletName())
.bpn(miwSettings.authorityWalletBpn())
.build();
createWallet(request, true, miwSettings.authorityWalletBpn());
wallet[0] = createWallet(request, true, miwSettings.authorityWalletBpn());
log.info("Authority wallet created with bpn {}", StringEscapeUtils.escapeJava(miwSettings.authorityWalletBpn()));
} else {
log.info("Authority wallet exists with bpn {}", StringEscapeUtils.escapeJava(miwSettings.authorityWalletBpn()));
}
}
});
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@SneakyThrows
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
if (wallet[0] != null) {
jwtPresentationES256KService.storeWalletKeyES256K(wallet[0]);
}
}
});
}

private void validateCreateWallet(CreateWalletRequest request, String callerBpn) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@
-- liquibase formatted sql
-- changeset andreibogus: add column algorithm to wallet_key table

ALTER TABLE public.wallet_key ADD algorithm varchar(255) NOT NULL;
ALTER TABLE public.wallet_key ADD algorithm varchar(255) NOT NULL DEFAULT 'ED25519';

0 comments on commit b694d19

Please sign in to comment.