11package ee .cyber .cdoc2 .crypto ;
22
3+ import ee .cyber .cdoc2 .auth .EtsiIdentifier ;
34import ee .cyber .cdoc2 .client .KeyShareClientFactory ;
45import ee .cyber .cdoc2 .client .KeySharesClient ;
6+ import ee .cyber .cdoc2 .client .mobileid .MobileIdClient ;
57import ee .cyber .cdoc2 .client .model .KeyShare ;
68import ee .cyber .cdoc2 .client .smartid .SmartIdClient ;
79import ee .cyber .cdoc2 .container .CDocParseException ;
3133import java .security .KeyPair ;
3234import java .security .interfaces .ECPublicKey ;
3335import java .security .interfaces .RSAPrivateKey ;
34- import java .util .ArrayList ;
36+ import java .util .LinkedList ;
3537import java .util .List ;
3638import java .util .NoSuchElementException ;
39+ import java .util .Objects ;
3740import java .util .Optional ;
3841import javax .crypto .SecretKey ;
3942
4043import ee .cyber .cdoc2 .services .Services ;
41- import ee .cyber .cdoc2 .util .SIDAuthTokenCreator ;
44+ import ee .cyber .cdoc2 .crypto .jwt .IdentityJWSSigner ;
45+ import ee .cyber .cdoc2 .crypto .jwt .MIDAuthJWSSigner ;
46+ import ee .cyber .cdoc2 .crypto .jwt .SIDAuthJWSSigner ;
47+ import ee .cyber .cdoc2 .crypto .jwt .SidMidAuthTokenCreator ;
48+ import ee .sk .smartid .rest .dao .SemanticsIdentifier ;
4249import org .slf4j .Logger ;
4350import org .slf4j .LoggerFactory ;
4451
45- import static ee .cyber .cdoc2 .crypto .AuthenticationIdentifier .ETSI_IDENTIFIER_PREFIX ;
46-
4752
4853/**
4954 * Functions for deriving KEK in different scenarios
@@ -258,80 +263,115 @@ public static byte[] deriveKekFromShares(
258263 KeyShareClientFactory keyShareClientFactory ,
259264 Services services //XXX: for now its generic services, in future might be more specific type to use SID/MID
260265 ) throws GeneralSecurityException , CDocException {
266+
267+ Objects .requireNonNull (services );
261268 validateKeyOrigin (
262269 EncryptionKeyOrigin .KEY_SHARE ,
263270 keyMaterial .getKeyOrigin (),
264271 "Expected key shares for KeySharesRecipient"
265272 );
266273
267- if ( services == null || ! services . hasService ( SmartIdClient . class )) {
268- throw new CDocException ( "SmartIdClient not configured" );
269- }
274+ try {
275+ List < byte []> listOfShares =
276+ fetchKeyShares ( keyMaterial , keySharesRecipient , keyShareClientFactory , services );
270277
271- List <KeyShareUri > shares = keySharesRecipient .getKeyShares ();
272- List <byte []> listOfShares = new ArrayList <>();
278+ return Crypto .combineKek (
279+ listOfShares ,
280+ keyShareClientFactory .getKeySharesConfiguration ().getKeySharesServersMinNum ()
281+ );
273282
274- try {
275- addKeyShares (listOfShares , keyMaterial , keySharesRecipient , keyShareClientFactory , services );
276283 } catch (AuthSignatureCreationException asce ) {
277284 throw new GeneralSecurityException (asce );
278285 }
279286
280- return Crypto .combineKek (
281- listOfShares ,
282- keyShareClientFactory .getKeySharesConfiguration ().getKeySharesServersMinNum ()
283- );
284287 }
285288
286- private static void addKeyShares (
287- List <byte []> listOfShares ,
289+ private static List <byte []> fetchKeyShares (
288290 KeyShareDecryptionKeyMaterial decryptKeyMaterial ,
289291 KeySharesRecipient keySharesRecipient ,
290292 KeyShareClientFactory keyShareClientFactory ,
291293 Services services
292- ) throws GeneralSecurityException , AuthSignatureCreationException {
293-
294- //FIXME: write proper implementation with RM-4309, RM-4032, RM-4073
295- String semanticsIdentifier = String .valueOf (keySharesRecipient .getRecipientId ()) // etsi/PNOEE-48010010101
296- .substring (ETSI_IDENTIFIER_PREFIX .length ()); // PNOEE-48010010101
294+ ) throws GeneralSecurityException , AuthSignatureCreationException , CDocException {
297295
296+ List <byte []> listOfShares = new LinkedList <>();
298297 List <KeyShareUri > shares = keySharesRecipient .getKeyShares ();
299298
300- AuthenticationIdentifier .AuthenticationType authType
301- = decryptKeyMaterial .authIdentifier ().getAuthType ();
299+ SidMidAuthTokenCreator tokenCreator =
300+ signShareAccessTokens (shares , decryptKeyMaterial , keyShareClientFactory , services );
301+
302+ for (KeyShareUri share : shares ) {
303+ listOfShares .add (getKeyShare (share , keyShareClientFactory , tokenCreator ));
304+ }
305+ return listOfShares ;
306+ }
307+
308+ /**
309+ * Ask nonce for each share, sign share with nonce using auth means
310+ * @param shares
311+ * @param decryptKeyMaterial
312+ * @param keyShareClientFactory
313+ * @param services
314+ * @return
315+ * @throws CDocException
316+ * @throws AuthSignatureCreationException
317+ */
318+ private static SidMidAuthTokenCreator signShareAccessTokens (
319+ List <KeyShareUri > shares ,
320+ KeyShareDecryptionKeyMaterial decryptKeyMaterial ,
321+ KeyShareClientFactory keyShareClientFactory ,
322+ Services services
323+
324+ ) throws CDocException , AuthSignatureCreationException {
325+
326+ AuthenticationIdentifier .AuthenticationType authType =
327+ decryptKeyMaterial .authIdentifier ().getAuthType ();
328+ SemanticsIdentifier semanticsIdentifier =
329+ decryptKeyMaterial .authIdentifier ().getSemanticsIdentifier ();
330+ EtsiIdentifier etsiIdentifier = new EtsiIdentifier (decryptKeyMaterial .authIdentifier ().getEtsiIdentifier ());
302331
303332 switch (authType ) {
304333 case SID -> {
305- SIDAuthTokenCreator tokenCreator = new SIDAuthTokenCreator (
306- semanticsIdentifier ,
307- shares ,
308- keyShareClientFactory ,
309- services .get (SmartIdClient .class ));
310- for (KeyShareUri share : shares ) {
311- listOfShares .add (extractSharesFromSidRecipient (keyShareClientFactory , tokenCreator , share ));
334+ if (!services .hasService (SmartIdClient .class )) {
335+ throw new CDocException ("SmartIdClient not configured" );
312336 }
337+ SmartIdClient sidClient = services .get (SmartIdClient .class );
338+ return new SidMidAuthTokenCreator (
339+ new SIDAuthJWSSigner (sidClient , semanticsIdentifier ),
340+ shares ,
341+ keyShareClientFactory );
313342 }
314343 case MID -> {
315- // ToDo connect authentication here. RM-4609
316- // MobileIdUserData userData = new MobileIdUserData(
317- // decryptKeyMaterial.authIdentifier().getMobileNumber(),
318- // decryptKeyMaterial.authIdentifier().getIdCode()
319- // );
320- // MobileIdClient.startAuthentication(userData);
321- for (KeyShareUri share : shares ) {
322- listOfShares .add (extractSharesFromMidRecipient (keyShareClientFactory , share ));
344+ if (!services .hasService (MobileIdClient .class )) {
345+ throw new CDocException ("MobileIdClient not configured" );
323346 }
347+ MobileIdClient midClient = services .get (MobileIdClient .class );
348+ String mobileNumber = decryptKeyMaterial .authIdentifier ().getMobileNumber ();
349+ IdentityJWSSigner jwsSigner = new MIDAuthJWSSigner (midClient , etsiIdentifier , mobileNumber );
350+
351+ // constructor gets nonce for each share from shares-server and signs shareUris and their nonces
352+ // with jwsSigner
353+ return new SidMidAuthTokenCreator (
354+ jwsSigner ,
355+ shares ,
356+ keyShareClientFactory );
324357 }
325358 default -> throw new IllegalStateException (
326359 "Unexpected authentication type: " + authType
327360 );
328361 }
329362 }
330363
331- private static byte [] extractSharesFromSidRecipient (
364+ /**
365+ * @param keyShareClientFactory
366+ * @param tokenCreator signed authentication token
367+ * @param share share to fetch
368+ * @return
369+ * @throws GeneralSecurityException
370+ */
371+ private static byte [] getKeyShare (
372+ KeyShareUri share ,
332373 KeyShareClientFactory keyShareClientFactory ,
333- SIDAuthTokenCreator tokenCreator ,
334- KeyShareUri share
374+ SidMidAuthTokenCreator tokenCreator
335375 ) throws GeneralSecurityException {
336376 KeySharesClient client
337377 = keyShareClientFactory .getClientForServerUrl (share .serverBaseUrl ());
@@ -341,20 +381,6 @@ private static byte[] extractSharesFromSidRecipient(
341381 return getKeyShare (share , client , authTicket , authenticatorCertPEM );
342382 }
343383
344- // ToDo add authentication token here. RM-4609
345- private static byte [] extractSharesFromMidRecipient (
346- KeyShareClientFactory keyShareClientFactory ,
347- // MIDAuthTokenCreator tokenCreator
348- KeyShareUri share
349- ) throws GeneralSecurityException {
350- KeySharesClient client
351- = keyShareClientFactory .getClientForServerUrl (share .serverBaseUrl ());
352- // String authTicket = tokenCreator.getTokenForShareID(share.shareId());
353- // String authenticatorCertPEM = tokenCreator.getAuthenticatorCertPEM();
354-
355- return getKeyShare (share , client , null , null );
356- }
357-
358384 private static byte [] getKeyShare (
359385 KeyShareUri share ,
360386 KeySharesClient client ,
0 commit comments