gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] branch master updated: new blind signing code builds


From: gnunet
Subject: [taler-exchange] branch master updated: new blind signing code builds
Date: Fri, 27 Oct 2023 20:08:56 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 82d7d87c new blind signing code builds
     new 47397c55 Merge branch 'master' of git+ssh://git.taler.net/exchange
82d7d87c is described below

commit 82d7d87cc3946a01bfed221c7da0fb9ef2c18eb1
Author: Christian Grothoff <grothoff@gnunet.org>
AuthorDate: Wed Oct 25 22:54:20 2023 +0200

    new blind signing code builds
---
 src/auditor/taler-helper-auditor-coins.c           |   6 +-
 src/auditor/taler-helper-auditor-reserves.c        |   2 +-
 src/auditordb/test_auditordb.c                     |   2 +-
 src/benchmark/taler-aggregator-benchmark.c         |  15 +-
 src/exchange-tools/taler-exchange-offline.c        |  21 +-
 src/exchange/taler-exchange-httpd_age-withdraw.c   |   7 +-
 .../taler-exchange-httpd_age-withdraw_reveal.c     |  45 +-
 src/exchange/taler-exchange-httpd_batch-deposit.c  |   9 +-
 src/exchange/taler-exchange-httpd_batch-withdraw.c |  21 +-
 src/exchange/taler-exchange-httpd_common_deposit.c |   9 +-
 src/exchange/taler-exchange-httpd_csr.c            |  49 +-
 src/exchange/taler-exchange-httpd_keys.c           | 143 +++--
 src/exchange/taler-exchange-httpd_keys.h           |  12 +-
 src/exchange/taler-exchange-httpd_melt.c           |   6 +-
 src/exchange/taler-exchange-httpd_recoup-refresh.c |  33 +-
 src/exchange/taler-exchange-httpd_recoup.c         |  31 +-
 .../taler-exchange-httpd_refreshes_reveal.c        |  70 +--
 src/exchangedb/perf_deposits_get_ready.c           |  18 +-
 src/exchangedb/perf_get_link_data.c                |  17 +-
 src/exchangedb/perf_select_refunds_by_coin.c       |  18 +-
 src/exchangedb/pg_do_batch_withdraw_insert.c       |   2 +-
 src/exchangedb/pg_do_batch_withdraw_insert.h       |   2 +-
 src/exchangedb/pg_do_recoup.c                      |   2 +-
 src/exchangedb/pg_do_recoup.h                      |   2 +-
 src/exchangedb/pg_do_recoup_refresh.c              |   2 +-
 src/exchangedb/pg_do_recoup_refresh.h              |   2 +-
 src/exchangedb/pg_get_link_data.c                  |   5 +-
 src/exchangedb/pg_get_refresh_reveal.c             |   3 +-
 src/exchangedb/pg_select_recoup_above_serial_id.c  |   2 +-
 .../pg_select_recoup_refresh_above_serial_id.c     |   2 +-
 src/exchangedb/test_exchangedb.c                   |  16 +-
 src/include/taler_crypto_lib.h                     | 366 +++---------
 src/include/taler_exchange_service.h               |  12 +-
 src/include/taler_exchangedb_plugin.h              |  30 +-
 src/include/taler_json_lib.h                       |   3 +-
 src/include/taler_testing_lib.h                    |   2 +-
 src/json/json_helper.c                             | 209 ++++---
 src/json/json_pack.c                               | 124 ++--
 src/lib/exchange_api_age_withdraw.c                |  82 +--
 src/lib/exchange_api_batch_withdraw.c              |  35 +-
 src/lib/exchange_api_csr_melt.c                    |   3 +-
 src/lib/exchange_api_csr_withdraw.c                |   9 +-
 src/lib/exchange_api_handle.c                      |  18 +-
 src/lib/exchange_api_link.c                        |  19 +-
 src/lib/exchange_api_management_get_keys.c         |  18 +-
 src/lib/exchange_api_melt.c                        |  21 +-
 src/lib/exchange_api_recoup.c                      |  42 +-
 src/lib/exchange_api_recoup_refresh.c              |  45 +-
 src/lib/exchange_api_refresh_common.c              |  32 +-
 src/lib/exchange_api_refresh_common.h              |   2 +-
 src/lib/exchange_api_refreshes_reveal.c            |   5 +-
 src/pq/pq_query_helper.c                           | 147 ++---
 src/pq/pq_result_helper.c                          | 188 +++---
 src/testing/testing_api_cmd_batch_withdraw.c       |   2 +-
 src/testing/testing_api_cmd_insert_deposit.c       |  15 +-
 src/testing/testing_api_cmd_refresh.c              |   2 +-
 src/testing/testing_api_cmd_withdraw.c             |   2 +-
 src/util/crypto.c                                  |  39 +-
 src/util/crypto_helper_cs.c                        |  61 +-
 src/util/crypto_helper_rsa.c                       |  47 +-
 src/util/denom.c                                   | 641 +++++----------------
 src/util/taler-exchange-secmod-cs.c                |  67 +--
 src/util/taler-exchange-secmod-cs.h                |  18 +-
 src/util/taler-exchange-secmod-rsa.c               |  37 +-
 src/util/test_crypto.c                             |  93 ++-
 src/util/test_helper_cs.c                          | 122 ++--
 src/util/test_helper_rsa.c                         | 106 ++--
 src/util/wallet_signatures.c                       |  10 +-
 68 files changed, 1464 insertions(+), 1784 deletions(-)

diff --git a/src/auditor/taler-helper-auditor-coins.c 
b/src/auditor/taler-helper-auditor-coins.c
index bc1598b0..41c4f520 100644
--- a/src/auditor/taler-helper-auditor-coins.c
+++ b/src/auditor/taler-helper-auditor-coins.c
@@ -1940,7 +1940,7 @@ check_recoup (struct CoinContext *cc,
               const struct TALER_CoinPublicInfo *coin,
               const struct TALER_DenominationPublicKey *denom_pub,
               const struct TALER_CoinSpendSignatureP *coin_sig,
-              const union TALER_DenominationBlindingKeyP *coin_blind)
+              const union GNUNET_CRYPTO_BlindingSecretP *coin_blind)
 {
   struct DenominationSummary *ds;
   enum GNUNET_DB_QueryStatus qs;
@@ -2071,7 +2071,7 @@ recoup_cb (void *cls,
            const struct TALER_CoinPublicInfo *coin,
            const struct TALER_DenominationPublicKey *denom_pub,
            const struct TALER_CoinSpendSignatureP *coin_sig,
-           const union TALER_DenominationBlindingKeyP *coin_blind)
+           const union GNUNET_CRYPTO_BlindingSecretP *coin_blind)
 {
   struct CoinContext *cc = cls;
 
@@ -2139,7 +2139,7 @@ recoup_refresh_cb (void *cls,
                    const struct TALER_CoinPublicInfo *coin,
                    const struct TALER_DenominationPublicKey *denom_pub,
                    const struct TALER_CoinSpendSignatureP *coin_sig,
-                   const union TALER_DenominationBlindingKeyP *coin_blind)
+                   const union GNUNET_CRYPTO_BlindingSecretP *coin_blind)
 {
   struct CoinContext *cc = cls;
   const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue;
diff --git a/src/auditor/taler-helper-auditor-reserves.c 
b/src/auditor/taler-helper-auditor-reserves.c
index eca3c42a..f589ebfd 100644
--- a/src/auditor/taler-helper-auditor-reserves.c
+++ b/src/auditor/taler-helper-auditor-reserves.c
@@ -678,7 +678,7 @@ handle_recoup_by_reserve (
   const struct TALER_CoinPublicInfo *coin,
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_CoinSpendSignatureP *coin_sig,
-  const union TALER_DenominationBlindingKeyP *coin_blind)
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_blind)
 {
   struct ReserveContext *rc = cls;
   struct ReserveSummary *rs;
diff --git a/src/auditordb/test_auditordb.c b/src/auditordb/test_auditordb.c
index d39d08b9..f8fbe66c 100644
--- a/src/auditordb/test_auditordb.c
+++ b/src/auditordb/test_auditordb.c
@@ -248,7 +248,7 @@ run (void *cls)
   GNUNET_assert (GNUNET_OK ==
                  TALER_denom_priv_create (&denom_priv,
                                           &denom_pub,
-                                          TALER_DENOMINATION_RSA,
+                                          GNUNET_CRYPTO_BSA_RSA,
                                           1024));
   TALER_denom_pub_hash (&denom_pub,
                         &denom_pub_hash);
diff --git a/src/benchmark/taler-aggregator-benchmark.c 
b/src/benchmark/taler-aggregator-benchmark.c
index 9b2b1d4f..228d050e 100644
--- a/src/benchmark/taler-aggregator-benchmark.c
+++ b/src/benchmark/taler-aggregator-benchmark.c
@@ -489,18 +489,18 @@ run (void *cls,
     struct TALER_PlanchetDetail pd;
     struct TALER_BlindedDenominationSignature bds;
     struct TALER_PlanchetMasterSecretP ps;
-    struct TALER_ExchangeWithdrawValues alg_values;
     struct TALER_CoinSpendPublicKeyP coin_pub;
     struct TALER_AgeCommitmentHash hac;
-    union TALER_DenominationBlindingKeyP bks;
+    union GNUNET_CRYPTO_BlindingSecretP bks;
+    const struct TALER_ExchangeWithdrawValues *alg_values;
 
     RANDOMIZE (&coin_pub);
     GNUNET_assert (GNUNET_OK ==
                    TALER_denom_priv_create (&pk,
                                             &denom_pub,
-                                            TALER_DENOMINATION_RSA,
+                                            GNUNET_CRYPTO_BSA_RSA,
                                             1024));
-    alg_values.cipher = TALER_DENOMINATION_RSA;
+    alg_values = TALER_denom_ewv_rsa_singleton ();
     denom_pub.age_mask = issue.age_mask;
     TALER_denom_pub_hash (&denom_pub,
                           &h_denom_pub);
@@ -522,7 +522,7 @@ run (void *cls,
     }
 
     TALER_planchet_blinding_secret_create (&ps,
-                                           &alg_values,
+                                           TALER_denom_ewv_rsa_singleton (),
                                            &bks);
 
     {
@@ -546,9 +546,10 @@ run (void *cls,
     GNUNET_assert (GNUNET_OK ==
                    TALER_denom_blind (&denom_pub,
                                       &bks,
+                                      NULL,
                                       &hac,
                                       &coin_pub,
-                                      &alg_values,
+                                      alg_values,
                                       &c_hash,
                                       &pd.blinded_planchet));
     GNUNET_assert (GNUNET_OK ==
@@ -562,7 +563,7 @@ run (void *cls,
                                             &bds,
                                             &bks,
                                             &c_hash,
-                                            &alg_values,
+                                            alg_values,
                                             &denom_pub));
     TALER_blinded_denom_sig_free (&bds);
     TALER_denom_pub_free (&denom_pub);
diff --git a/src/exchange-tools/taler-exchange-offline.c 
b/src/exchange-tools/taler-exchange-offline.c
index fed29437..3eb0ba46 100644
--- a/src/exchange-tools/taler-exchange-offline.c
+++ b/src/exchange-tools/taler-exchange-offline.c
@@ -4305,13 +4305,13 @@ show_denomkeys (const struct 
TALER_SecurityModulePublicKeyP *secm_pub_rsa,
       stamp_expire_withdraw.abs_time);
     TALER_denom_pub_hash (&denom_pub,
                           &h_denom_pub);
-    switch (denom_pub.cipher)
+    switch (denom_pub.bsign_pub_key->cipher)
     {
-    case TALER_DENOMINATION_RSA:
+    case GNUNET_CRYPTO_BSA_RSA:
       {
         struct TALER_RsaPubHashP h_rsa;
 
-        TALER_rsa_pub_hash (denom_pub.details.rsa_public_key,
+        TALER_rsa_pub_hash (denom_pub.bsign_pub_key->details.rsa_public_key,
                             &h_rsa);
         ok = TALER_exchange_secmod_rsa_verify (&h_rsa,
                                                section_name,
@@ -4321,11 +4321,11 @@ show_denomkeys (const struct 
TALER_SecurityModulePublicKeyP *secm_pub_rsa,
                                                &secm_sig);
       }
       break;
-    case TALER_DENOMINATION_CS:
+    case GNUNET_CRYPTO_BSA_CS:
       {
         struct TALER_CsPubHashP h_cs;
 
-        TALER_cs_pub_hash (&denom_pub.details.cs_public_key,
+        TALER_cs_pub_hash (&denom_pub.bsign_pub_key->details.cs_public_key,
                            &h_cs);
         ok = TALER_exchange_secmod_cs_verify (&h_cs,
                                               section_name,
@@ -4785,13 +4785,14 @@ sign_denomkeys (const struct 
TALER_SecurityModulePublicKeyP *secm_pub_rsa,
 
     TALER_denom_pub_hash (&denom_pub,
                           &h_denom_pub);
-    switch (denom_pub.cipher)
+
+    switch (denom_pub.bsign_pub_key->cipher)
     {
-    case TALER_DENOMINATION_RSA:
+    case GNUNET_CRYPTO_BSA_RSA:
       {
         struct TALER_RsaPubHashP h_rsa;
 
-        TALER_rsa_pub_hash (denom_pub.details.rsa_public_key,
+        TALER_rsa_pub_hash (denom_pub.bsign_pub_key->details.rsa_public_key,
                             &h_rsa);
         if (GNUNET_OK !=
             TALER_exchange_secmod_rsa_verify (&h_rsa,
@@ -4811,11 +4812,11 @@ sign_denomkeys (const struct 
TALER_SecurityModulePublicKeyP *secm_pub_rsa,
         }
       }
       break;
-    case TALER_DENOMINATION_CS:
+    case GNUNET_CRYPTO_BSA_CS:
       {
         struct TALER_CsPubHashP h_cs;
 
-        TALER_cs_pub_hash (&denom_pub.details.cs_public_key,
+        TALER_cs_pub_hash (&denom_pub.bsign_pub_key->details.cs_public_key,
                            &h_cs);
         if (GNUNET_OK !=
             TALER_exchange_secmod_cs_verify (&h_cs,
diff --git a/src/exchange/taler-exchange-httpd_age-withdraw.c 
b/src/exchange/taler-exchange-httpd_age-withdraw.c
index 4a7d6b1a..56065dda 100644
--- a/src/exchange/taler-exchange-httpd_age-withdraw.c
+++ b/src/exchange/taler-exchange-httpd_age-withdraw.c
@@ -448,7 +448,8 @@ are_denominations_valid (
       return GNUNET_SYSERR;
 
     /* Ensure the ciphers from the planchets match the denominations' */
-    if (dk->denom_pub.cipher != coin_evs[i].cipher)
+    if (dk->denom_pub.bsign_pub_key->cipher !=
+        coin_evs[i].blinded_message->cipher)
     {
       GNUNET_break_op (0);
       *result = TALER_MHD_reply_with_ec (connection,
@@ -863,8 +864,8 @@ sign_and_do_age_withdraw (
       csds[i].h_denom_pub = &awc->denom_hs[i];
     }
 
-    ec = TEH_keys_denomination_batch_sign (csds,
-                                           awc->num_coins,
+    ec = TEH_keys_denomination_batch_sign (awc->num_coins,
+                                           csds,
                                            false,
                                            denom_sigs);
     if (TALER_EC_NONE != ec)
diff --git a/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c 
b/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c
index b77b5e37..7463d222 100644
--- a/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c
+++ b/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c
@@ -307,50 +307,47 @@ calculate_blinded_hash (
     struct TALER_CoinPubHashP c_hash;
     struct TALER_PlanchetDetail detail = {0};
     struct TALER_CoinSpendPrivateKeyP coin_priv;
-    union TALER_DenominationBlindingKeyP bks;
+    union GNUNET_CRYPTO_BlindingSecretP bks;
+    struct GNUNET_CRYPTO_BlindingInputValues bi = {
+      .cipher = denom_key->denom_pub.bsign_pub_key->cipher
+    };
     struct TALER_ExchangeWithdrawValues alg_values = {
-      .cipher = denom_key->denom_pub.cipher,
+      .blinding_inputs = &bi
     };
+    union GNUNET_CRYPTO_BlindSessionNonce nonce;
+    union GNUNET_CRYPTO_BlindSessionNonce *noncep = NULL;
 
-    if (TALER_DENOMINATION_CS == alg_values.cipher)
+    // FIXME: add logic to denom.c to do this!
+    if (GNUNET_CRYPTO_BSA_CS == bi.cipher)
     {
-      struct TALER_CsNonce nonce;
+      struct TEH_CsDeriveData cdd = {
+        .h_denom_pub = &denom_key->h_denom_pub,
+        .nonce = &nonce.cs_nonce,
+      };
 
       TALER_cs_withdraw_nonce_derive (secret,
-                                      &nonce);
-
-      {
-        struct TEH_CsDeriveData cdd = {
-          .h_denom_pub = &denom_key->h_denom_pub,
-          .nonce = &nonce,
-        };
-
-        GNUNET_assert (TALER_EC_NONE ==
-                       TEH_keys_denomination_cs_r_pub (
-                         &cdd,
-                         false,
-                         &alg_values.details.cs_values));
-      }
-
-      detail.blinded_planchet.details.cs_blinded_planchet.nonce = nonce;
+                                      &nonce.cs_nonce);
+      noncep = &nonce;
+      GNUNET_assert (TALER_EC_NONE ==
+                     TEH_keys_denomination_cs_r_pub (
+                       &cdd,
+                       false,
+                       &bi.details.cs_values));
     }
-
     TALER_planchet_blinding_secret_create (secret,
                                            &alg_values,
                                            &bks);
-
     TALER_planchet_setup_coin_priv (secret,
                                     &alg_values,
                                     &coin_priv);
-
     ret = TALER_planchet_prepare (&denom_key->denom_pub,
                                   &alg_values,
                                   &bks,
+                                  noncep,
                                   &coin_priv,
                                   &ach,
                                   &c_hash,
                                   &detail);
-
     if (GNUNET_OK != ret)
     {
       GNUNET_break (0);
diff --git a/src/exchange/taler-exchange-httpd_batch-deposit.c 
b/src/exchange/taler-exchange-httpd_batch-deposit.c
index 87ca36e0..32c39adc 100644
--- a/src/exchange/taler-exchange-httpd_batch-deposit.c
+++ b/src/exchange/taler-exchange-httpd_batch-deposit.c
@@ -376,7 +376,8 @@ parse_coin (struct MHD_Connection *connection,
         ? GNUNET_NO
         : GNUNET_SYSERR;
     }
-    if (dk->denom_pub.cipher != cdi->coin.denom_sig.cipher)
+    if (dk->denom_pub.bsign_pub_key->cipher !=
+        cdi->coin.denom_sig.unblinded_sig->cipher)
     {
       /* denomination cipher and denomination signature cipher not the same */
       GNUNET_JSON_parse_free (spec);
@@ -391,12 +392,12 @@ parse_coin (struct MHD_Connection *connection,
 
     *deposit_fee = dk->meta.fees.deposit;
     /* check coin signature */
-    switch (dk->denom_pub.cipher)
+    switch (dk->denom_pub.bsign_pub_key->cipher)
     {
-    case TALER_DENOMINATION_RSA:
+    case GNUNET_CRYPTO_BSA_RSA:
       TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_RSA]++;
       break;
-    case TALER_DENOMINATION_CS:
+    case GNUNET_CRYPTO_BSA_CS:
       TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_CS]++;
       break;
     default:
diff --git a/src/exchange/taler-exchange-httpd_batch-withdraw.c 
b/src/exchange/taler-exchange-httpd_batch-withdraw.c
index fe210876..19a9cacf 100644
--- a/src/exchange/taler-exchange-httpd_batch-withdraw.c
+++ b/src/exchange/taler-exchange-httpd_batch-withdraw.c
@@ -534,14 +534,22 @@ batch_withdraw_transaction (void *cls,
   {
     struct PlanchetContext *pc = &wc->planchets[i];
     const struct TALER_BlindedPlanchet *bp = &pc->blinded_planchet;
-    const struct TALER_CsNonce *nonce;
+    const union GNUNET_CRYPTO_BlindSessionNonce *nonce = NULL;
     bool denom_unknown = true;
     bool conflict = true;
     bool nonce_reuse = true;
 
-    nonce = (TALER_DENOMINATION_CS == bp->cipher)
-            ? &bp->details.cs_blinded_planchet.nonce
-            : NULL;
+    switch (bp->blinded_message->cipher)
+    {
+    case GNUNET_CRYPTO_BSA_INVALID:
+      break;
+    case GNUNET_CRYPTO_BSA_RSA:
+      break;
+    case GNUNET_CRYPTO_BSA_CS:
+      nonce = (const union GNUNET_CRYPTO_BlindSessionNonce *)
+              &bp->blinded_message->details.cs_blinded_message.nonce;
+      break;
+    }
     qs = TEH_plugin->do_batch_withdraw_insert (TEH_plugin->cls,
                                                nonce,
                                                &pc->collectable,
@@ -626,8 +634,8 @@ prepare_transaction (const struct TEH_RequestContext *rc,
     enum TALER_ErrorCode ec;
 
     ec = TEH_keys_denomination_batch_sign (
-      csds,
       wc->planchets_length,
+      csds,
       false,
       bss);
     if (TALER_EC_NONE != ec)
@@ -797,7 +805,8 @@ parse_planchets (const struct TEH_RequestContext *rc,
       }
       return mret;
     }
-    if (dk->denom_pub.cipher != pc->blinded_planchet.cipher)
+    if (dk->denom_pub.bsign_pub_key->cipher !=
+        pc->blinded_planchet.blinded_message->cipher)
     {
       /* denomination cipher and blinded planchet cipher not the same */
       GNUNET_break_op (0);
diff --git a/src/exchange/taler-exchange-httpd_common_deposit.c 
b/src/exchange/taler-exchange-httpd_common_deposit.c
index 0c91f0bc..898e23dd 100644
--- a/src/exchange/taler-exchange-httpd_common_deposit.c
+++ b/src/exchange/taler-exchange-httpd_common_deposit.c
@@ -135,7 +135,8 @@ TEH_common_purse_deposit_parse_coin (
                 "PURSE CREATE"))
              ? GNUNET_NO : GNUNET_SYSERR;
     }
-    if (dk->denom_pub.cipher != coin->cpi.denom_sig.cipher)
+    if (dk->denom_pub.bsign_pub_key->cipher !=
+        coin->cpi.denom_sig.unblinded_sig->cipher)
     {
       /* denomination cipher and denomination signature cipher not the same */
       GNUNET_JSON_parse_free (spec);
@@ -164,12 +165,12 @@ TEH_common_purse_deposit_parse_coin (
                                           &coin->deposit_fee));
 
     /* check coin signature */
-    switch (dk->denom_pub.cipher)
+    switch (dk->denom_pub.bsign_pub_key->cipher)
     {
-    case TALER_DENOMINATION_RSA:
+    case GNUNET_CRYPTO_BSA_RSA:
       TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_RSA]++;
       break;
-    case TALER_DENOMINATION_CS:
+    case GNUNET_CRYPTO_BSA_CS:
       TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_CS]++;
       break;
     default:
diff --git a/src/exchange/taler-exchange-httpd_csr.c 
b/src/exchange/taler-exchange-httpd_csr.c
index 64892d36..e4fa4f5e 100644
--- a/src/exchange/taler-exchange-httpd_csr.c
+++ b/src/exchange/taler-exchange-httpd_csr.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2022 Taler Systems SA
+  Copyright (C) 2014-2023 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as
@@ -21,6 +21,7 @@
  * @brief Handle /csr requests
  * @author Lucien Heuzeveldt
  * @author Gian Demarmles
+ * @author Christian Grothoff
  */
 #include "platform.h"
 #include <gnunet/gnunet_util_lib.h>
@@ -74,12 +75,12 @@ TEH_handler_csr_melt (struct TEH_RequestContext *rc,
   }
 
   {
-    struct TALER_ExchangeWithdrawValues ewvs[csr_requests_num];
+    struct GNUNET_CRYPTO_BlindingInputValues ewvs[csr_requests_num];
     {
-      struct TALER_CsNonce nonces[csr_requests_num];
+      struct GNUNET_CRYPTO_CsSessionNonce nonces[csr_requests_num];
       struct TALER_DenominationHashP denom_pub_hashes[csr_requests_num];
       struct TEH_CsDeriveData cdds[csr_requests_num];
-      struct TALER_DenominationCSPublicRPairP r_pubs[csr_requests_num];
+      struct GNUNET_CRYPTO_CSPublicRPairP r_pubs[csr_requests_num];
 
       for (unsigned int i = 0; i < csr_requests_num; i++)
       {
@@ -110,11 +111,11 @@ TEH_handler_csr_melt (struct TEH_RequestContext *rc,
 
       for (unsigned int i = 0; i < csr_requests_num; i++)
       {
-        const struct TALER_CsNonce *nonce = &nonces[i];
+        const struct GNUNET_CRYPTO_CsSessionNonce *nonce = &nonces[i];
         const struct TALER_DenominationHashP *denom_pub_hash =
           &denom_pub_hashes[i];
 
-        ewvs[i].cipher = TALER_DENOMINATION_CS;
+        ewvs[i].cipher = GNUNET_CRYPTO_BSA_CS;
         /* check denomination referenced by denom_pub_hash */
         {
           struct TEH_KeyStateHandle *ksh;
@@ -165,7 +166,8 @@ TEH_handler_csr_melt (struct TEH_RequestContext *rc,
               TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
               "csr-melt");
           }
-          if (TALER_DENOMINATION_CS != dk->denom_pub.cipher)
+          if (GNUNET_CRYPTO_BSA_CS !=
+              dk->denom_pub.bsign_pub_key->cipher)
           {
             /* denomination is valid but not for CS */
             return TEH_RESPONSE_reply_invalid_denom_cipher_for_operation (
@@ -176,8 +178,8 @@ TEH_handler_csr_melt (struct TEH_RequestContext *rc,
         cdds[i].h_denom_pub = denom_pub_hash;
         cdds[i].nonce = nonce;
       } /* for (i) */
-      ec = TEH_keys_denomination_cs_batch_r_pub (cdds,
-                                                 csr_requests_num,
+      ec = TEH_keys_denomination_cs_batch_r_pub (csr_requests_num,
+                                                 cdds,
                                                  true,
                                                  r_pubs);
       if (TALER_EC_NONE != ec)
@@ -200,10 +202,13 @@ TEH_handler_csr_melt (struct TEH_RequestContext *rc,
       for (unsigned int i = 0; i < csr_requests_num; i++)
       {
         json_t *csr_obj;
+        struct TALER_ExchangeWithdrawValues exw = {
+          .blinding_inputs = &ewvs[i]
+        };
 
         csr_obj = GNUNET_JSON_PACK (
           TALER_JSON_pack_exchange_withdraw_values ("ewv",
-                                                    &ewvs[i]));
+                                                    &exw));
         GNUNET_assert (NULL != csr_obj);
         GNUNET_assert (0 ==
                        json_array_append_new (csr_response_ewvs,
@@ -226,10 +231,10 @@ TEH_handler_csr_withdraw (struct TEH_RequestContext *rc,
                           const json_t *root,
                           const char *const args[])
 {
-  struct TALER_CsNonce nonce;
+  struct GNUNET_CRYPTO_CsSessionNonce nonce;
   struct TALER_DenominationHashP denom_pub_hash;
-  struct TALER_ExchangeWithdrawValues ewv = {
-    .cipher = TALER_DENOMINATION_CS
+  struct GNUNET_CRYPTO_BlindingInputValues ewv = {
+    .cipher = GNUNET_CRYPTO_BSA_CS
   };
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_fixed_auto ("nonce",
@@ -300,7 +305,8 @@ TEH_handler_csr_withdraw (struct TEH_RequestContext *rc,
         TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
         "csr-withdraw");
     }
-    if (TALER_DENOMINATION_CS != dk->denom_pub.cipher)
+    if (GNUNET_CRYPTO_BSA_CS !=
+        dk->denom_pub.bsign_pub_key->cipher)
     {
       /* denomination is valid but not for CS */
       return TEH_RESPONSE_reply_invalid_denom_cipher_for_operation (
@@ -328,12 +334,17 @@ TEH_handler_csr_withdraw (struct TEH_RequestContext *rc,
                                       NULL);
     }
   }
+  {
+    struct TALER_ExchangeWithdrawValues exw = {
+      .blinding_inputs = &ewv
+    };
 
-  return TALER_MHD_REPLY_JSON_PACK (
-    rc->connection,
-    MHD_HTTP_OK,
-    TALER_JSON_pack_exchange_withdraw_values ("ewv",
-                                              &ewv));
+    return TALER_MHD_REPLY_JSON_PACK (
+      rc->connection,
+      MHD_HTTP_OK,
+      TALER_JSON_pack_exchange_withdraw_values ("ewv",
+                                                &exw));
+  }
 }
 
 
diff --git a/src/exchange/taler-exchange-httpd_keys.c 
b/src/exchange/taler-exchange-httpd_keys.c
index 27b9d6c7..fd6b18b3 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -1185,12 +1185,20 @@ check_dk (void *cls,
 
   (void) cls;
   (void) hc;
-  GNUNET_assert (TALER_DENOMINATION_INVALID != dk->denom_pub.cipher);
-  if (TALER_DENOMINATION_RSA == dk->denom_pub.cipher)
+  switch (dk->denom_pub.bsign_pub_key->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     GNUNET_assert (GNUNET_CRYPTO_rsa_public_key_check (
-                     dk->denom_pub.details.rsa_public_key));
-  // nothing to do for TALER_DENOMINATION_CS
-  return GNUNET_OK;
+                     dk->denom_pub.bsign_pub_key->details.rsa_public_key));
+    return GNUNET_OK;
+  case GNUNET_CRYPTO_BSA_CS:
+    /* nothing to do for GNUNET_CRYPTO_BSA_CS */
+    return GNUNET_OK;
+  }
+  GNUNET_assert (0);
+  return GNUNET_SYSERR;
 }
 
 
@@ -1471,7 +1479,7 @@ load_age_mask (const char *section_name)
  * @param validity_duration how long does the key remain available for signing;
  *                 zero if the key has been revoked or purged
  * @param h_rsa hash of the @a denom_pub that is available (or was purged)
- * @param denom_pub the public key itself, NULL if the key was revoked or 
purged
+ * @param bs_pub the public key itself, NULL if the key was revoked or purged
  * @param sm_pub public key of the security module, NULL if the key was 
revoked or purged
  * @param sm_sig signature from the security module, NULL if the key was 
revoked or purged
  *               The signature was already verified against @a sm_pub.
@@ -1483,7 +1491,7 @@ helper_rsa_cb (
   struct GNUNET_TIME_Timestamp start_time,
   struct GNUNET_TIME_Relative validity_duration,
   const struct TALER_RsaPubHashP *h_rsa,
-  const struct TALER_DenominationPublicKey *denom_pub,
+  struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub,
   const struct TALER_SecurityModulePublicKeyP *sm_pub,
   const struct TALER_SecurityModuleSignatureP *sm_sig)
 {
@@ -1513,10 +1521,9 @@ helper_rsa_cb (
   hd->validity_duration = validity_duration;
   hd->h_details.h_rsa = *h_rsa;
   hd->sm_sig = *sm_sig;
-  GNUNET_assert (TALER_DENOMINATION_RSA == denom_pub->cipher);
-  TALER_denom_pub_deep_copy (&hd->denom_pub,
-                             denom_pub);
-  GNUNET_assert (TALER_DENOMINATION_RSA == hd->denom_pub.cipher);
+  GNUNET_assert (GNUNET_CRYPTO_BSA_RSA == bs_pub->cipher);
+  hd->denom_pub.bsign_pub_key =
+    GNUNET_CRYPTO_bsign_pub_incref (bs_pub);
   /* load the age mask for the denomination, if applicable */
   hd->denom_pub.age_mask = load_age_mask (section_name);
   TALER_denom_pub_hash (&hd->denom_pub,
@@ -1552,7 +1559,7 @@ helper_rsa_cb (
  * @param validity_duration how long does the key remain available for signing;
  *                 zero if the key has been revoked or purged
  * @param h_cs hash of the @a denom_pub that is available (or was purged)
- * @param denom_pub the public key itself, NULL if the key was revoked or 
purged
+ * @param bs_pub the public key itself, NULL if the key was revoked or purged
  * @param sm_pub public key of the security module, NULL if the key was 
revoked or purged
  * @param sm_sig signature from the security module, NULL if the key was 
revoked or purged
  *               The signature was already verified against @a sm_pub.
@@ -1564,7 +1571,7 @@ helper_cs_cb (
   struct GNUNET_TIME_Timestamp start_time,
   struct GNUNET_TIME_Relative validity_duration,
   const struct TALER_CsPubHashP *h_cs,
-  const struct TALER_DenominationPublicKey *denom_pub,
+  struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub,
   const struct TALER_SecurityModulePublicKeyP *sm_pub,
   const struct TALER_SecurityModuleSignatureP *sm_sig)
 {
@@ -1594,9 +1601,9 @@ helper_cs_cb (
   hd->validity_duration = validity_duration;
   hd->h_details.h_cs = *h_cs;
   hd->sm_sig = *sm_sig;
-  GNUNET_assert (TALER_DENOMINATION_CS == denom_pub->cipher);
-  TALER_denom_pub_deep_copy (&hd->denom_pub,
-                             denom_pub);
+  GNUNET_assert (GNUNET_CRYPTO_BSA_CS == bs_pub->cipher);
+  hd->denom_pub.bsign_pub_key
+    = GNUNET_CRYPTO_bsign_pub_incref (bs_pub);
   /* load the age mask for the denomination, if applicable */
   hd->denom_pub.age_mask = load_age_mask (section_name);
   TALER_denom_pub_hash (&hd->denom_pub,
@@ -1975,7 +1982,8 @@ denomination_info_cb (
     return;
   }
 
-  GNUNET_assert (TALER_DENOMINATION_INVALID != denom_pub->cipher);
+  GNUNET_assert (GNUNET_CRYPTO_BSA_INVALID !=
+                 denom_pub->bsign_pub_key->cipher);
   if (GNUNET_TIME_absolute_is_zero (meta->start.abs_time) ||
       GNUNET_TIME_absolute_is_zero (meta->expire_withdraw.abs_time) ||
       GNUNET_TIME_absolute_is_zero (meta->expire_deposit.abs_time) ||
@@ -2995,7 +3003,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
         json_t *entry;
         struct GNUNET_HashCode key;
         struct TALER_DenominationGroup meta = {
-          .cipher = dk->denom_pub.cipher,
+          .cipher = dk->denom_pub.bsign_pub_key->cipher,
           .value = dk->meta.value,
           .fees = dk->meta.fees,
           .age_mask = dk->meta.age_mask,
@@ -3016,10 +3024,10 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
           group = GNUNET_new (struct GroupData);
           switch (meta.cipher)
           {
-          case TALER_DENOMINATION_RSA:
+          case GNUNET_CRYPTO_BSA_RSA:
             cipher = age_restricted ? "RSA+age_restricted" : "RSA";
             break;
-          case TALER_DENOMINATION_CS:
+          case GNUNET_CRYPTO_BSA_CS:
             cipher = age_restricted ? "CS+age_restricted" : "CS";
             break;
           default:
@@ -3080,18 +3088,18 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
                   hd->validity_duration));
           switch (meta.cipher)
           {
-          case TALER_DENOMINATION_RSA:
+          case GNUNET_CRYPTO_BSA_RSA:
             key_spec =
               GNUNET_JSON_pack_rsa_public_key (
                 "rsa_pub",
-                dk->denom_pub.details.rsa_public_key);
+                dk->denom_pub.bsign_pub_key->details.rsa_public_key);
             break;
-          case TALER_DENOMINATION_CS:
+          case GNUNET_CRYPTO_BSA_CS:
             key_spec =
               GNUNET_JSON_pack_data_varsize (
                 "cs_pub",
-                &dk->denom_pub.details.cs_public_key,
-                sizeof (dk->denom_pub.details.cs_public_key));
+                &dk->denom_pub.bsign_pub_key->details.cs_public_key,
+                sizeof (dk->denom_pub.bsign_pub_key->details.cs_public_key));
             break;
           default:
             GNUNET_assert (false);
@@ -3564,17 +3572,21 @@ TEH_keys_denomination_sign (
                                           &h_denom_pub->hash);
   if (NULL == hd)
     return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
-  if (bp->cipher != hd->denom_pub.cipher)
+  if (bp->blinded_message->cipher !=
+      hd->denom_pub.bsign_pub_key->cipher)
     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
-  switch (hd->denom_pub.cipher)
+  switch (hd->denom_pub.bsign_pub_key->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     TEH_METRICS_num_signatures[TEH_MT_SIGNATURE_RSA]++;
     {
       struct TALER_CRYPTO_RsaSignRequest rsr = {
         .h_rsa = &hd->h_details.h_rsa,
-        .msg = bp->details.rsa_blinded_planchet.blinded_msg,
-        .msg_size = bp->details.rsa_blinded_planchet.blinded_msg_size
+        .msg = bp->blinded_message->details.rsa_blinded_message.blinded_msg,
+        .msg_size =
+          bp->blinded_message->details.rsa_blinded_message.blinded_msg_size
       };
 
       return TALER_CRYPTO_helper_rsa_sign (
@@ -3582,31 +3594,30 @@ TEH_keys_denomination_sign (
         &rsr,
         bs);
     }
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     TEH_METRICS_num_signatures[TEH_MT_SIGNATURE_CS]++;
     {
       struct TALER_CRYPTO_CsSignRequest csr;
 
       csr.h_cs = &hd->h_details.h_cs;
-      csr.blinded_planchet = &bp->details.cs_blinded_planchet;
+      csr.blinded_planchet = &bp->blinded_message->details.cs_blinded_message;
       return TALER_CRYPTO_helper_cs_sign (
         ksh->helpers->csdh,
         &csr,
         for_melt,
         bs);
     }
-  default:
-    return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
   }
+  return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
 }
 
 
 enum TALER_ErrorCode
 TEH_keys_denomination_batch_sign (
-  const struct TEH_CoinSignData *csds,
   unsigned int csds_length,
+  const struct TEH_CoinSignData csds[static csds_length],
   bool for_melt,
-  struct TALER_BlindedDenominationSignature *bss)
+  struct TALER_BlindedDenominationSignature bss[static csds_length])
 {
   struct TEH_KeyStateHandle *ksh;
   struct HelperDenomination *hd;
@@ -3630,21 +3641,23 @@ TEH_keys_denomination_batch_sign (
                                             &h_denom_pub->hash);
     if (NULL == hd)
       return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
-    if (bp->cipher != hd->denom_pub.cipher)
+    if (bp->blinded_message->cipher !=
+        hd->denom_pub.bsign_pub_key->cipher)
       return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
-    switch (hd->denom_pub.cipher)
+    switch (hd->denom_pub.bsign_pub_key->cipher)
     {
-    case TALER_DENOMINATION_RSA:
+    case GNUNET_CRYPTO_BSA_RSA:
       rsrs[rsrs_pos].h_rsa = &hd->h_details.h_rsa;
       rsrs[rsrs_pos].msg
-        = bp->details.rsa_blinded_planchet.blinded_msg;
+        = bp->blinded_message->details.rsa_blinded_message.blinded_msg;
       rsrs[rsrs_pos].msg_size
-        = bp->details.rsa_blinded_planchet.blinded_msg_size;
+        = bp->blinded_message->details.rsa_blinded_message.blinded_msg_size;
       rsrs_pos++;
       break;
-    case TALER_DENOMINATION_CS:
+    case GNUNET_CRYPTO_BSA_CS:
       csrs[csrs_pos].h_cs = &hd->h_details.h_cs;
-      csrs[csrs_pos].blinded_planchet = &bp->details.cs_blinded_planchet;
+      csrs[csrs_pos].blinded_planchet
+        = &bp->blinded_message->details.cs_blinded_message;
       csrs_pos++;
       break;
     default:
@@ -3667,8 +3680,8 @@ TEH_keys_denomination_batch_sign (
   {
     ec = TALER_CRYPTO_helper_cs_batch_sign (
       ksh->helpers->csdh,
-      csrs,
       csrs_pos,
+      csrs,
       for_melt,
       (0 == rsrs_pos) ? bss : cs);
     if (TALER_EC_NONE != ec)
@@ -3683,8 +3696,8 @@ TEH_keys_denomination_batch_sign (
   {
     ec = TALER_CRYPTO_helper_rsa_batch_sign (
       ksh->helpers->rsadh,
-      rsrs,
       rsrs_pos,
+      rsrs,
       (0 == csrs_pos) ? bss : rs);
     if (TALER_EC_NONE != ec)
     {
@@ -3706,12 +3719,12 @@ TEH_keys_denomination_batch_sign (
     {
       const struct TALER_BlindedPlanchet *bp = csds[i].bp;
 
-      switch (bp->cipher)
+      switch (bp->blinded_message->cipher)
       {
-      case TALER_DENOMINATION_RSA:
+      case GNUNET_CRYPTO_BSA_RSA:
         bss[i] = rs[rsrs_pos++];
         break;
-      case TALER_DENOMINATION_CS:
+      case GNUNET_CRYPTO_BSA_CS:
         bss[i] = cs[csrs_pos++];
         break;
       default:
@@ -3727,10 +3740,10 @@ enum TALER_ErrorCode
 TEH_keys_denomination_cs_r_pub (
   const struct TEH_CsDeriveData *cdd,
   bool for_melt,
-  struct TALER_DenominationCSPublicRPairP *r_pub)
+  struct GNUNET_CRYPTO_CSPublicRPairP *r_pub)
 {
   const struct TALER_DenominationHashP *h_denom_pub = cdd->h_denom_pub;
-  const struct TALER_CsNonce *nonce = cdd->nonce;
+  const struct GNUNET_CRYPTO_CsSessionNonce *nonce = cdd->nonce;
   struct TEH_KeyStateHandle *ksh;
   struct HelperDenomination *hd;
 
@@ -3745,7 +3758,8 @@ TEH_keys_denomination_cs_r_pub (
   {
     return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
   }
-  if (TALER_DENOMINATION_CS != hd->denom_pub.cipher)
+  if (GNUNET_CRYPTO_BSA_CS !=
+      hd->denom_pub.bsign_pub_key->cipher)
   {
     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
   }
@@ -3765,10 +3779,10 @@ TEH_keys_denomination_cs_r_pub (
 
 enum TALER_ErrorCode
 TEH_keys_denomination_cs_batch_r_pub (
-  const struct TEH_CsDeriveData *cdds,
   unsigned int cdds_length,
+  const struct TEH_CsDeriveData cdds[static cdds_length],
   bool for_melt,
-  struct TALER_DenominationCSPublicRPairP *r_pubs)
+  struct GNUNET_CRYPTO_CSPublicRPairP r_pubs[static cdds_length])
 {
   struct TEH_KeyStateHandle *ksh;
   struct HelperDenomination *hd;
@@ -3782,7 +3796,7 @@ TEH_keys_denomination_cs_batch_r_pub (
   for (unsigned int i = 0; i<cdds_length; i++)
   {
     const struct TALER_DenominationHashP *h_denom_pub = cdds[i].h_denom_pub;
-    const struct TALER_CsNonce *nonce = cdds[i].nonce;
+    const struct GNUNET_CRYPTO_CsSessionNonce *nonce = cdds[i].nonce;
 
     hd = GNUNET_CONTAINER_multihashmap_get (ksh->helpers->denom_keys,
                                             &h_denom_pub->hash);
@@ -3790,7 +3804,8 @@ TEH_keys_denomination_cs_batch_r_pub (
     {
       return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
     }
-    if (TALER_DENOMINATION_CS != hd->denom_pub.cipher)
+    if (GNUNET_CRYPTO_BSA_CS !=
+        hd->denom_pub.bsign_pub_key->cipher)
     {
       return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
     }
@@ -3799,8 +3814,8 @@ TEH_keys_denomination_cs_batch_r_pub (
   }
 
   return TALER_CRYPTO_helper_cs_r_batch_derive (ksh->helpers->csdh,
-                                                cdrs,
                                                 cdds_length,
+                                                cdrs,
                                                 for_melt,
                                                 r_pubs);
 }
@@ -3825,22 +3840,23 @@ TEH_keys_denomination_revoke (const struct 
TALER_DenominationHashP *h_denom_pub)
     GNUNET_break (0);
     return;
   }
-  switch (hd->denom_pub.cipher)
+  switch (hd->denom_pub.bsign_pub_key->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     TALER_CRYPTO_helper_rsa_revoke (ksh->helpers->rsadh,
                                     &hd->h_details.h_rsa);
     TEH_keys_update_states ();
     return;
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     TALER_CRYPTO_helper_cs_revoke (ksh->helpers->csdh,
                                    &hd->h_details.h_cs);
     TEH_keys_update_states ();
     return;
-  default:
-    GNUNET_break (0);
-    return;
   }
+  GNUNET_break (0);
+  return;
 }
 
 
@@ -4170,7 +4186,8 @@ TEH_keys_load_fees (struct TEH_KeyStateHandle *ksh,
                             meta);
   if (GNUNET_OK == ok)
   {
-    GNUNET_assert (TALER_DENOMINATION_INVALID != hd->denom_pub.cipher);
+    GNUNET_assert (GNUNET_CRYPTO_BSA_INVALID !=
+                   hd->denom_pub.bsign_pub_key->cipher);
     TALER_denom_pub_deep_copy (denom_pub,
                                &hd->denom_pub);
   }
diff --git a/src/exchange/taler-exchange-httpd_keys.h 
b/src/exchange/taler-exchange-httpd_keys.h
index e170b978..5baa8b30 100644
--- a/src/exchange/taler-exchange-httpd_keys.h
+++ b/src/exchange/taler-exchange-httpd_keys.h
@@ -325,10 +325,10 @@ TEH_keys_denomination_sign (
  */
 enum TALER_ErrorCode
 TEH_keys_denomination_batch_sign (
-  const struct TEH_CoinSignData *csds,
   unsigned int csds_length,
+  const struct TEH_CoinSignData csds[static csds_length],
   bool for_melt,
-  struct TALER_BlindedDenominationSignature *bss);
+  struct TALER_BlindedDenominationSignature bss[static csds_length]);
 
 
 /**
@@ -344,7 +344,7 @@ struct TEH_CsDeriveData
   /**
    * Nonce to use.
    */
-  const struct TALER_CsNonce *nonce;
+  const struct GNUNET_CRYPTO_CsSessionNonce *nonce;
 };
 
 
@@ -360,7 +360,7 @@ enum TALER_ErrorCode
 TEH_keys_denomination_cs_r_pub (
   const struct TEH_CsDeriveData *cdd,
   bool for_melt,
-  struct TALER_DenominationCSPublicRPairP *r_pub);
+  struct GNUNET_CRYPTO_CSPublicRPairP *r_pub);
 
 
 /**
@@ -375,10 +375,10 @@ TEH_keys_denomination_cs_r_pub (
  */
 enum TALER_ErrorCode
 TEH_keys_denomination_cs_batch_r_pub (
-  const struct TEH_CsDeriveData *cdds,
   unsigned int cdds_length,
+  const struct TEH_CsDeriveData cdds[static cdds_length],
   bool for_melt,
-  struct TALER_DenominationCSPublicRPairP *r_pubs);
+  struct GNUNET_CRYPTO_CSPublicRPairP r_pubs[static cdds_length]);
 
 
 /**
diff --git a/src/exchange/taler-exchange-httpd_melt.c 
b/src/exchange/taler-exchange-httpd_melt.c
index 1e5c92e1..f8aea95c 100644
--- a/src/exchange/taler-exchange-httpd_melt.c
+++ b/src/exchange/taler-exchange-httpd_melt.c
@@ -338,12 +338,12 @@ check_melt_valid (struct MHD_Connection *connection,
                                        
TALER_EC_EXCHANGE_MELT_FEES_EXCEED_CONTRIBUTION,
                                        NULL);
   }
-  switch (dk->denom_pub.cipher)
+  switch (dk->denom_pub.bsign_pub_key->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_RSA]++;
     break;
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_CS]++;
     break;
   default:
diff --git a/src/exchange/taler-exchange-httpd_recoup-refresh.c 
b/src/exchange/taler-exchange-httpd_recoup-refresh.c
index d52dabda..a5d5b2ab 100644
--- a/src/exchange/taler-exchange-httpd_recoup-refresh.c
+++ b/src/exchange/taler-exchange-httpd_recoup-refresh.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2017-2021 Taler Systems SA
+  Copyright (C) 2017-2023 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -55,7 +55,7 @@ struct RecoupContext
   /**
    * Key used to blind the coin.
    */
-  const union TALER_DenominationBlindingKeyP *coin_bks;
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks;
 
   /**
    * Signature of the coin requesting recoup.
@@ -175,8 +175,8 @@ verify_and_execute_recoup_refresh (
   struct MHD_Connection *connection,
   const struct TALER_CoinPublicInfo *coin,
   const struct TALER_ExchangeWithdrawValues *exchange_vals,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
-  const struct TALER_CsNonce *nonce,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
+  const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
   const struct TALER_CoinSpendSignatureP *coin_sig)
 {
   struct RecoupContext pc;
@@ -219,12 +219,12 @@ verify_and_execute_recoup_refresh (
   }
 
   /* check denomination signature */
-  switch (dk->denom_pub.cipher)
+  switch (dk->denom_pub.bsign_pub_key->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_RSA]++;
     break;
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_CS]++;
     break;
   default:
@@ -265,6 +265,7 @@ verify_and_execute_recoup_refresh (
     if (GNUNET_OK !=
         TALER_denom_blind (&dk->denom_pub,
                            coin_bks,
+                           nonce,
                            &coin->h_age_commitment,
                            &coin->coin_pub,
                            exchange_vals,
@@ -278,9 +279,6 @@ verify_and_execute_recoup_refresh (
         TALER_EC_EXCHANGE_RECOUP_REFRESH_BLINDING_FAILED,
         NULL);
     }
-    if (TALER_DENOMINATION_CS == blinded_planchet.cipher)
-      blinded_planchet.details.cs_blinded_planchet.nonce
-        = *nonce;
     TALER_coin_ev_hash (&blinded_planchet,
                         &coin->denom_pub_hash,
                         &h_blind);
@@ -375,10 +373,11 @@ TEH_handler_recoup_refresh (struct MHD_Connection 
*connection,
 {
   enum GNUNET_GenericReturnValue ret;
   struct TALER_CoinPublicInfo coin = {0};
-  union TALER_DenominationBlindingKeyP coin_bks;
+  union GNUNET_CRYPTO_BlindingSecretP coin_bks;
   struct TALER_CoinSpendSignatureP coin_sig;
   struct TALER_ExchangeWithdrawValues exchange_vals;
-  struct TALER_CsNonce nonce;
+  union GNUNET_CRYPTO_BlindSessionNonce nonce;
+  bool no_nonce;
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
                                  &coin.denom_pub_hash),
@@ -394,19 +393,17 @@ TEH_handler_recoup_refresh (struct MHD_Connection 
*connection,
       GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
                                    &coin.h_age_commitment),
       &coin.no_age_commitment),
+    // FIXME: rename to just 'nonce'
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("cs_nonce",
                                    &nonce),
-      NULL),
+      &no_nonce),
     GNUNET_JSON_spec_end ()
   };
 
   memset (&coin,
           0,
           sizeof (coin));
-  memset (&nonce,
-          0,
-          sizeof (nonce));
   coin.coin_pub = *coin_pub;
   ret = TALER_MHD_parse_json_data (connection,
                                    root,
@@ -422,7 +419,9 @@ TEH_handler_recoup_refresh (struct MHD_Connection 
*connection,
                                              &coin,
                                              &exchange_vals,
                                              &coin_bks,
-                                             &nonce,
+                                             no_nonce
+                                             ? NULL
+                                             : &nonce,
                                              &coin_sig);
     GNUNET_JSON_parse_free (spec);
     return res;
diff --git a/src/exchange/taler-exchange-httpd_recoup.c 
b/src/exchange/taler-exchange-httpd_recoup.c
index 349c2b94..6173ca6c 100644
--- a/src/exchange/taler-exchange-httpd_recoup.c
+++ b/src/exchange/taler-exchange-httpd_recoup.c
@@ -58,7 +58,7 @@ struct RecoupContext
   /**
    * Key used to blind the coin.
    */
-  const union TALER_DenominationBlindingKeyP *coin_bks;
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks;
 
   /**
    * Signature of the coin requesting recoup.
@@ -178,8 +178,8 @@ verify_and_execute_recoup (
   struct MHD_Connection *connection,
   const struct TALER_CoinPublicInfo *coin,
   const struct TALER_ExchangeWithdrawValues *exchange_vals,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
-  const struct TALER_CsNonce *nonce,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
+  const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
   const struct TALER_CoinSpendSignatureP *coin_sig)
 {
   struct RecoupContext pc;
@@ -221,12 +221,12 @@ verify_and_execute_recoup (
   }
 
   /* check denomination signature */
-  switch (dk->denom_pub.cipher)
+  switch (dk->denom_pub.bsign_pub_key->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_RSA]++;
     break;
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_CS]++;
     break;
   default:
@@ -270,6 +270,7 @@ verify_and_execute_recoup (
     if (GNUNET_OK !=
         TALER_denom_blind (&dk->denom_pub,
                            coin_bks,
+                           nonce,
                            &coin->h_age_commitment,
                            &coin->coin_pub,
                            exchange_vals,
@@ -283,9 +284,6 @@ verify_and_execute_recoup (
         TALER_EC_EXCHANGE_RECOUP_BLINDING_FAILED,
         NULL);
     }
-    if (TALER_DENOMINATION_CS == blinded_planchet.cipher)
-      blinded_planchet.details.cs_blinded_planchet.nonce
-        = *nonce;
     if (GNUNET_OK !=
         TALER_coin_ev_hash (&blinded_planchet,
                             &coin->denom_pub_hash,
@@ -388,10 +386,11 @@ TEH_handler_recoup (struct MHD_Connection *connection,
 {
   enum GNUNET_GenericReturnValue ret;
   struct TALER_CoinPublicInfo coin;
-  union TALER_DenominationBlindingKeyP coin_bks;
+  union GNUNET_CRYPTO_BlindingSecretP coin_bks;
   struct TALER_CoinSpendSignatureP coin_sig;
   struct TALER_ExchangeWithdrawValues exchange_vals;
-  struct TALER_CsNonce nonce;
+  union GNUNET_CRYPTO_BlindSessionNonce nonce;
+  bool no_nonce;
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
                                  &coin.denom_pub_hash),
@@ -407,19 +406,17 @@ TEH_handler_recoup (struct MHD_Connection *connection,
       GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
                                    &coin.h_age_commitment),
       &coin.no_age_commitment),
+    // FIXME: should be renamed to just 'nonce'!
     GNUNET_JSON_spec_mark_optional (
       GNUNET_JSON_spec_fixed_auto ("cs_nonce",
                                    &nonce),
-      NULL),
+      &no_nonce),
     GNUNET_JSON_spec_end ()
   };
 
   memset (&coin,
           0,
           sizeof (coin));
-  memset (&nonce,
-          0,
-          sizeof (nonce));
   coin.coin_pub = *coin_pub;
   ret = TALER_MHD_parse_json_data (connection,
                                    root,
@@ -435,7 +432,9 @@ TEH_handler_recoup (struct MHD_Connection *connection,
                                      &coin,
                                      &exchange_vals,
                                      &coin_bks,
-                                     &nonce,
+                                     no_nonce
+                                     ? NULL
+                                     : &nonce,
                                      &coin_sig);
     GNUNET_JSON_parse_free (spec);
     return res;
diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.c 
b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
index 81a08623..0509bc90 100644
--- a/src/exchange/taler-exchange-httpd_refreshes_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
@@ -156,14 +156,17 @@ check_commitment (struct RevealContext *rctx,
                   struct MHD_Connection *connection,
                   MHD_RESULT *mhd_ret)
 {
-  struct TALER_CsNonce nonces[rctx->num_fresh_coins];
-  unsigned int aoff = 0;
+  const union GNUNET_CRYPTO_BlindSessionNonce *nonces[rctx->num_fresh_coins];
 
+  memset (nonces,
+          0,
+          sizeof (nonces));
   for (unsigned int j = 0; j<rctx->num_fresh_coins; j++)
   {
     const struct TALER_DenominationPublicKey *dk = &rctx->dks[j]->denom_pub;
 
-    if (dk->cipher != rctx->rcds[j].blinded_planchet.cipher)
+    if (dk->bsign_pub_key->cipher !=
+        rctx->rcds[j].blinded_planchet.blinded_message->cipher)
     {
       GNUNET_break (0);
       *mhd_ret = TALER_MHD_reply_with_error (
@@ -173,9 +176,9 @@ check_commitment (struct RevealContext *rctx,
         NULL);
       return GNUNET_SYSERR;
     }
-    switch (dk->cipher)
+    switch (dk->bsign_pub_key->cipher)
     {
-    case TALER_DENOMINATION_INVALID:
+    case GNUNET_CRYPTO_BSA_INVALID:
       GNUNET_break (0);
       *mhd_ret = TALER_MHD_reply_with_error (
         connection,
@@ -183,44 +186,48 @@ check_commitment (struct RevealContext *rctx,
         TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
         NULL);
       return GNUNET_SYSERR;
-    case TALER_DENOMINATION_RSA:
+    case GNUNET_CRYPTO_BSA_RSA:
       continue;
-    case TALER_DENOMINATION_CS:
-      nonces[aoff]
-        = rctx->rcds[j].blinded_planchet.details.cs_blinded_planchet.nonce;
-      aoff++;
+    case GNUNET_CRYPTO_BSA_CS:
+      nonces[j]
+        = (const union GNUNET_CRYPTO_BlindSessionNonce *)
+          &rctx->rcds[j].blinded_planchet.blinded_message->details.
+          cs_blinded_message.nonce;
       break;
     }
   }
 
   // OPTIMIZE: do this in batch later!
-  aoff = 0;
   for (unsigned int j = 0; j<rctx->num_fresh_coins; j++)
   {
     const struct TALER_DenominationPublicKey *dk = &rctx->dks[j]->denom_pub;
     struct TALER_ExchangeWithdrawValues *alg_values
       = &rctx->rrcs[j].exchange_vals;
+    struct GNUNET_CRYPTO_BlindingInputValues *bi;
 
-    alg_values->cipher = dk->cipher;
-    switch (dk->cipher)
+    bi = GNUNET_new (struct GNUNET_CRYPTO_BlindingInputValues);
+    alg_values->blinding_inputs = bi;
+    bi->rc = 1;
+    bi->cipher = dk->bsign_pub_key->cipher;
+    switch (dk->bsign_pub_key->cipher)
     {
-    case TALER_DENOMINATION_INVALID:
+    case GNUNET_CRYPTO_BSA_INVALID:
       GNUNET_assert (0);
       return GNUNET_SYSERR;
-    case TALER_DENOMINATION_RSA:
+    case GNUNET_CRYPTO_BSA_RSA:
       continue;
-    case TALER_DENOMINATION_CS:
+    case GNUNET_CRYPTO_BSA_CS:
       {
         enum TALER_ErrorCode ec;
         const struct TEH_CsDeriveData cdd = {
           .h_denom_pub = &rctx->rrcs[j].h_denom_pub,
-          .nonce = &nonces[aoff]
+          .nonce = &nonces[j]->cs_nonce
         };
 
         ec = TEH_keys_denomination_cs_r_pub (
           &cdd,
           true,
-          &alg_values->details.cs_values);
+          &bi->details.cs_values);
         if (TALER_EC_NONE != ec)
         {
           *mhd_ret = TALER_MHD_reply_with_error (connection,
@@ -229,7 +236,6 @@ check_commitment (struct RevealContext *rctx,
                                                  NULL);
           return GNUNET_SYSERR;
         }
-        aoff++;
       }
     }
   }
@@ -271,14 +277,11 @@ check_commitment (struct RevealContext *rctx,
                                            &ts);
         rce->new_coins = GNUNET_new_array (rctx->num_fresh_coins,
                                            struct TALER_RefreshCoinData);
-        aoff = 0;
         for (unsigned int j = 0; j<rctx->num_fresh_coins; j++)
         {
-          const struct TALER_DenominationPublicKey *dk
-            = &rctx->dks[j]->denom_pub;
           struct TALER_RefreshCoinData *rcd = &rce->new_coins[j];
           struct TALER_CoinSpendPrivateKeyP coin_priv;
-          union TALER_DenominationBlindingKeyP bks;
+          union GNUNET_CRYPTO_BlindingSecretP bks;
           const struct TALER_ExchangeWithdrawValues *alg_value
             = &rctx->rrcs[j].exchange_vals;
           struct TALER_PlanchetDetail pd = {0};
@@ -312,7 +315,8 @@ check_commitment (struct RevealContext *rctx,
                              &ts.key,
                              &nacp));
 
-            TALER_age_commitment_hash (&nacp.commitment, &h);
+            TALER_age_commitment_hash (&nacp.commitment,
+                                       &h);
             hac = &h;
           }
 
@@ -320,16 +324,11 @@ check_commitment (struct RevealContext *rctx,
                          TALER_planchet_prepare (rcd->dk,
                                                  alg_value,
                                                  &bks,
+                                                 nonces[j],
                                                  &coin_priv,
                                                  hac,
                                                  &c_hash,
                                                  &pd));
-          if (TALER_DENOMINATION_CS == dk->cipher)
-          {
-            pd.blinded_planchet.details.cs_blinded_planchet.nonce =
-              nonces[aoff];
-            aoff++;
-          }
           rcd->blinded_planchet = pd.blinded_planchet;
         }
       }
@@ -539,7 +538,8 @@ resolve_refreshes_reveal_denominations (
                                                        &ret);
     if (NULL == dks[i])
       return ret;
-    if ( (TALER_DENOMINATION_CS == dks[i]->denom_pub.cipher) &&
+    if ( (GNUNET_CRYPTO_BSA_CS ==
+          dks[i]->denom_pub.bsign_pub_key->cipher) &&
          (rctx->no_rms) )
     {
       return TALER_MHD_reply_with_error (
@@ -721,7 +721,8 @@ clean_age:
 
     rcd->blinded_planchet = rrc->blinded_planchet;
     rcd->dk = &dks[i]->denom_pub;
-    if (rcd->blinded_planchet.cipher != rcd->dk->cipher)
+    if (rcd->blinded_planchet.blinded_message->cipher !=
+        rcd->dk->bsign_pub_key->cipher)
     {
       GNUNET_break_op (0);
       ret = TALER_MHD_REPLY_JSON_PACK (
@@ -758,8 +759,8 @@ clean_age:
       csds[i].bp = &rcds[i].blinded_planchet;
     }
     ec = TEH_keys_denomination_batch_sign (
-      csds,
       rctx->num_fresh_coins,
+      csds,
       true,
       bss);
     if (TALER_EC_NONE != ec)
@@ -862,7 +863,10 @@ cleanup:
   for (unsigned int i = 0; i<num_fresh_coins; i++)
   {
     struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
+    struct TALER_ExchangeWithdrawValues *alg_values
+      = &rrcs[i].exchange_vals;
 
+    GNUNET_free (alg_values->blinding_inputs);
     TALER_blinded_denom_sig_free (&rrc->coin_sig);
     TALER_blinded_planchet_free (&rrc->blinded_planchet);
   }
diff --git a/src/exchangedb/perf_deposits_get_ready.c 
b/src/exchangedb/perf_deposits_get_ready.c
index f1566548..cba751e1 100644
--- a/src/exchangedb/perf_deposits_get_ready.c
+++ b/src/exchangedb/perf_deposits_get_ready.c
@@ -121,7 +121,7 @@ create_denom_key_pair (unsigned int size,
   GNUNET_assert (GNUNET_OK ==
                  TALER_denom_priv_create (&dkp->priv,
                                           &dkp->pub,
-                                          TALER_DENOMINATION_RSA,
+                                          GNUNET_CRYPTO_BSA_RSA,
                                           size));
   memset (&dki,
           0,
@@ -202,8 +202,12 @@ run (void *cls)
   unsigned int *perm;
   unsigned long long duration_sq;
   struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
+  struct GNUNET_CRYPTO_BlindingInputValues bi = {
+    .cipher = GNUNET_CRYPTO_BSA_RSA,
+    .rc = 0
+  };
   struct TALER_ExchangeWithdrawValues alg_values = {
-    .cipher = TALER_DENOMINATION_RSA
+    .blinding_inputs = &bi
   };
 
   ref = GNUNET_new_array (ROUNDS + 1,
@@ -262,7 +266,7 @@ run (void *cls)
     for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
     {
       struct GNUNET_TIME_Timestamp now;
-      struct TALER_BlindedRsaPlanchet *rp;
+      struct GNUNET_CRYPTO_RsaBlindedMessage *rp;
       struct TALER_BlindedPlanchet *bp;
 
       now = GNUNET_TIME_timestamp_get ();
@@ -274,8 +278,10 @@ run (void *cls)
       new_denom_pubs[cnt] = new_dkp[cnt]->pub;
       ccoin = &revealed_coins[cnt];
       bp = &ccoin->blinded_planchet;
-      bp->cipher = TALER_DENOMINATION_RSA;
-      rp = &bp->details.rsa_blinded_planchet;
+      bp->blinded_message = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage);
+      bp->blinded_message->cipher = GNUNET_CRYPTO_BSA_RSA;
+      bp->blinded_message->rc = 1;
+      rp = &bp->blinded_message->details.rsa_blinded_message;
       rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
         GNUNET_CRYPTO_QUALITY_WEAK,
         (RSA_KEY_SIZE / 8) - 1);
@@ -315,7 +321,7 @@ run (void *cls)
   for (unsigned int j = 0; j < NUM_ROWS; j++)
   {
     /*** NEED TO INSERT REFRESH COMMITMENTS + ENSURECOIN ***/
-    union TALER_DenominationBlindingKeyP bks;
+    union GNUNET_CRYPTO_BlindingSecretP bks;
     struct GNUNET_TIME_Timestamp deadline;
     struct TALER_CoinSpendPublicKeyP coin_pub;
     struct TALER_ReservePublicKeyP reserve_pub;
diff --git a/src/exchangedb/perf_get_link_data.c 
b/src/exchangedb/perf_get_link_data.c
index eb1f5f6e..817789af 100644
--- a/src/exchangedb/perf_get_link_data.c
+++ b/src/exchangedb/perf_get_link_data.c
@@ -110,7 +110,7 @@ create_denom_key_pair (unsigned int size,
   GNUNET_assert (GNUNET_OK ==
                  TALER_denom_priv_create (&dkp->priv,
                                           &dkp->pub,
-                                          TALER_DENOMINATION_RSA,
+                                          GNUNET_CRYPTO_BSA_RSA,
                                           size));
   memset (&dki,
           0,
@@ -208,8 +208,12 @@ run (void *cls)
   struct TALER_EXCHANGEDB_Refund *ref = NULL;
   unsigned int *perm;
   unsigned long long duration_sq;
+  struct GNUNET_CRYPTO_BlindingInputValues bi = {
+    .cipher = GNUNET_CRYPTO_BSA_RSA,
+    .rc = 0
+  };
   struct TALER_ExchangeWithdrawValues alg_values = {
-    .cipher = TALER_DENOMINATION_RSA
+    .blinding_inputs = &bi
   };
 
   ref = GNUNET_new_array (ROUNDS + 1,
@@ -280,7 +284,7 @@ run (void *cls)
                          "Transaction"));
   for (unsigned int j = 0; j < NUM_ROWS; j++)
   {
-    union TALER_DenominationBlindingKeyP bks;
+    union GNUNET_CRYPTO_BlindingSecretP bks;
     struct TALER_CoinPubHashP c_hash;
     unsigned int i = perm[j];
     uint64_t known_coin_id;
@@ -303,13 +307,16 @@ run (void *cls)
         struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coin =
           &revealed_coins[p];
         struct TALER_BlindedPlanchet *bp = &revealed_coin->blinded_planchet;
-        struct TALER_BlindedRsaPlanchet *rp = 
&bp->details.rsa_blinded_planchet;
+        bp->blinded_message = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage);
+        struct GNUNET_CRYPTO_RsaBlindedMessage *rp =
+          &bp->blinded_message->details.rsa_blinded_message;
 
         /* h_coin_ev must be unique, but we only have MELT_NEW_COINS created
            above for NUM_ROWS iterations; instead of making "all new" coins,
            we simply randomize the hash here as nobody is checking for 
consistency
            anyway ;-) */
-        bp->cipher = TALER_DENOMINATION_RSA;
+        bp->blinded_message->rc = 1;
+        bp->blinded_message->cipher = GNUNET_CRYPTO_BSA_RSA;
         rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
           GNUNET_CRYPTO_QUALITY_WEAK,
           (RSA_KEY_SIZE / 8) - 1);
diff --git a/src/exchangedb/perf_select_refunds_by_coin.c 
b/src/exchangedb/perf_select_refunds_by_coin.c
index fdb44d2c..8f2946fb 100644
--- a/src/exchangedb/perf_select_refunds_by_coin.c
+++ b/src/exchangedb/perf_select_refunds_by_coin.c
@@ -117,7 +117,7 @@ create_denom_key_pair (unsigned int size,
   GNUNET_assert (GNUNET_OK ==
                  TALER_denom_priv_create (&dkp->priv,
                                           &dkp->pub,
-                                          TALER_DENOMINATION_RSA,
+                                          GNUNET_CRYPTO_BSA_RSA,
                                           size));
   memset (&dki,
           0,
@@ -214,10 +214,14 @@ run (void *cls)
   struct TALER_EXCHANGEDB_CoinDepositInformation *depos = NULL;
   struct GNUNET_TIME_Timestamp deadline;
   struct TALER_Amount value;
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
   struct TALER_EXCHANGEDB_CollectableBlindcoin cbc;
+  struct GNUNET_CRYPTO_BlindingInputValues bi = {
+    .cipher = GNUNET_CRYPTO_BSA_RSA,
+    .rc = 0
+  };
   struct TALER_ExchangeWithdrawValues alg_values = {
-    .cipher = TALER_DENOMINATION_RSA
+    .blinding_inputs = &bi
   };
   struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO;
   unsigned long long sqrs = 0;
@@ -287,7 +291,7 @@ run (void *cls)
     for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
     {
       struct GNUNET_TIME_Timestamp now;
-      struct TALER_BlindedRsaPlanchet *rp;
+      struct GNUNET_CRYPTO_RsaBlindedMessage *rp;
       struct TALER_BlindedPlanchet *bp;
 
       now = GNUNET_TIME_timestamp_get ();
@@ -299,8 +303,10 @@ run (void *cls)
       new_denom_pubs[cnt] = new_dkp[cnt]->pub;
       ccoin = &revealed_coins[cnt];
       bp = &ccoin->blinded_planchet;
-      bp->cipher = TALER_DENOMINATION_RSA;
-      rp = &bp->details.rsa_blinded_planchet;
+      bp->blinded_message = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage);
+      bp->blinded_message->rc = 1;
+      bp->blinded_message->cipher = GNUNET_CRYPTO_BSA_RSA;
+      rp = &bp->blinded_message->details.rsa_blinded_message;
       rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
         GNUNET_CRYPTO_QUALITY_WEAK,
         (RSA_KEY_SIZE / 8) - 1);
diff --git a/src/exchangedb/pg_do_batch_withdraw_insert.c 
b/src/exchangedb/pg_do_batch_withdraw_insert.c
index b95a179d..758f502f 100644
--- a/src/exchangedb/pg_do_batch_withdraw_insert.c
+++ b/src/exchangedb/pg_do_batch_withdraw_insert.c
@@ -29,7 +29,7 @@
 enum GNUNET_DB_QueryStatus
 TEH_PG_do_batch_withdraw_insert (
   void *cls,
-  const struct TALER_CsNonce *nonce,
+  const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
   const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable,
   struct GNUNET_TIME_Timestamp now,
   uint64_t ruuid,
diff --git a/src/exchangedb/pg_do_batch_withdraw_insert.h 
b/src/exchangedb/pg_do_batch_withdraw_insert.h
index 6bc1a9a4..18fcfc9a 100644
--- a/src/exchangedb/pg_do_batch_withdraw_insert.h
+++ b/src/exchangedb/pg_do_batch_withdraw_insert.h
@@ -41,7 +41,7 @@
 enum GNUNET_DB_QueryStatus
 TEH_PG_do_batch_withdraw_insert (
   void *cls,
-  const struct TALER_CsNonce *nonce,
+  const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
   const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable,
   struct GNUNET_TIME_Timestamp now,
   uint64_t ruuid,
diff --git a/src/exchangedb/pg_do_recoup.c b/src/exchangedb/pg_do_recoup.c
index 1f74104e..07566a60 100644
--- a/src/exchangedb/pg_do_recoup.c
+++ b/src/exchangedb/pg_do_recoup.c
@@ -31,7 +31,7 @@ TEH_PG_do_recoup (
   void *cls,
   const struct TALER_ReservePublicKeyP *reserve_pub,
   uint64_t reserve_out_serial_id,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   uint64_t known_coin_id,
   const struct TALER_CoinSpendSignatureP *coin_sig,
diff --git a/src/exchangedb/pg_do_recoup.h b/src/exchangedb/pg_do_recoup.h
index 07a35078..2cf3eb97 100644
--- a/src/exchangedb/pg_do_recoup.h
+++ b/src/exchangedb/pg_do_recoup.h
@@ -45,7 +45,7 @@ TEH_PG_do_recoup (
   void *cls,
   const struct TALER_ReservePublicKeyP *reserve_pub,
   uint64_t reserve_out_serial_id,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   uint64_t known_coin_id,
   const struct TALER_CoinSpendSignatureP *coin_sig,
diff --git a/src/exchangedb/pg_do_recoup_refresh.c 
b/src/exchangedb/pg_do_recoup_refresh.c
index be5e4705..7d099bcd 100644
--- a/src/exchangedb/pg_do_recoup_refresh.c
+++ b/src/exchangedb/pg_do_recoup_refresh.c
@@ -30,7 +30,7 @@ TEH_PG_do_recoup_refresh (
   void *cls,
   const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
   uint64_t rrc_serial,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   uint64_t known_coin_id,
   const struct TALER_CoinSpendSignatureP *coin_sig,
diff --git a/src/exchangedb/pg_do_recoup_refresh.h 
b/src/exchangedb/pg_do_recoup_refresh.h
index fbd791d4..16b0fd20 100644
--- a/src/exchangedb/pg_do_recoup_refresh.h
+++ b/src/exchangedb/pg_do_recoup_refresh.h
@@ -46,7 +46,7 @@ TEH_PG_do_recoup_refresh (
   void *cls,
   const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
   uint64_t rrc_serial,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   uint64_t known_coin_id,
   const struct TALER_CoinSpendSignatureP *coin_sig,
diff --git a/src/exchangedb/pg_get_link_data.c 
b/src/exchangedb/pg_get_link_data.c
index 7fe6f996..a110c491 100644
--- a/src/exchangedb/pg_get_link_data.c
+++ b/src/exchangedb/pg_get_link_data.c
@@ -147,9 +147,10 @@ add_ldl (void *cls,
         ldctx->status = GNUNET_SYSERR;
         return;
       }
-      if (TALER_DENOMINATION_CS == bp.cipher)
+      if (GNUNET_CRYPTO_BSA_CS == bp.blinded_message->cipher)
       {
-        pos->nonce = bp.details.cs_blinded_planchet.nonce;
+        pos->nonce.cs_nonce
+          = bp.blinded_message->details.cs_blinded_message.nonce;
         pos->have_nonce = true;
       }
       TALER_blinded_planchet_free (&bp);
diff --git a/src/exchangedb/pg_get_refresh_reveal.c 
b/src/exchangedb/pg_get_refresh_reveal.c
index 07d63224..c0e3066d 100644
--- a/src/exchangedb/pg_get_refresh_reveal.c
+++ b/src/exchangedb/pg_get_refresh_reveal.c
@@ -112,7 +112,8 @@ add_revealed_coins (void *cls,
         GNUNET_PQ_result_spec_end
       };
 
-      if (TALER_DENOMINATION_INVALID != rrc->blinded_planchet.cipher)
+      if (NULL !=
+          rrc->blinded_planchet.blinded_message)
       {
         /* duplicate offset, not allowed */
         GNUNET_break (0);
diff --git a/src/exchangedb/pg_select_recoup_above_serial_id.c 
b/src/exchangedb/pg_select_recoup_above_serial_id.c
index 2ff30c7d..5791ee50 100644
--- a/src/exchangedb/pg_select_recoup_above_serial_id.c
+++ b/src/exchangedb/pg_select_recoup_above_serial_id.c
@@ -76,7 +76,7 @@ recoup_serial_helper_cb (void *cls,
     struct TALER_ReservePublicKeyP reserve_pub;
     struct TALER_CoinPublicInfo coin;
     struct TALER_CoinSpendSignatureP coin_sig;
-    union TALER_DenominationBlindingKeyP coin_blind;
+    union GNUNET_CRYPTO_BlindingSecretP coin_blind;
     struct TALER_Amount amount;
     struct TALER_DenominationPublicKey denom_pub;
     struct TALER_BlindedCoinHashP h_blind_ev;
diff --git a/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c 
b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c
index 22e09b46..22f90673 100644
--- a/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c
+++ b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c
@@ -76,7 +76,7 @@ recoup_refresh_serial_helper_cb (void *cls,
     struct TALER_CoinSpendPublicKeyP old_coin_pub;
     struct TALER_CoinPublicInfo coin;
     struct TALER_CoinSpendSignatureP coin_sig;
-    union TALER_DenominationBlindingKeyP coin_blind;
+    union GNUNET_CRYPTO_BlindingSecretP coin_blind;
     struct TALER_DenominationPublicKey denom_pub;
     struct TALER_DenominationHashP old_denom_pub_hash;
     struct TALER_Amount amount;
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index 336c1460..3c7c8f48 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -278,7 +278,7 @@ create_denom_key_pair (unsigned int size,
   GNUNET_assert (GNUNET_OK ==
                  TALER_denom_priv_create (&dkp->priv,
                                           &dkp->pub,
-                                          TALER_DENOMINATION_RSA,
+                                          GNUNET_CRYPTO_BSA_RSA,
                                           size));
   /* Using memset() as fields like master key and signature
      are not properly initialized for this test. */
@@ -1092,9 +1092,9 @@ recoup_cb (void *cls,
            const struct TALER_CoinPublicInfo *coin,
            const struct TALER_DenominationPublicKey *denom_pub,
            const struct TALER_CoinSpendSignatureP *coin_sig,
-           const union TALER_DenominationBlindingKeyP *coin_blind)
+           const union GNUNET_CRYPTO_BlindingSecretP *coin_blind)
 {
-  const union TALER_DenominationBlindingKeyP *cb = cls;
+  const union GNUNET_CRYPTO_BlindingSecretP *cb = cls;
 
   (void) rowid;
   (void) timestamp;
@@ -1177,7 +1177,7 @@ run (void *cls)
   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
   struct TALER_CoinSpendSignatureP coin_sig;
   struct GNUNET_TIME_Timestamp deadline;
-  union TALER_DenominationBlindingKeyP coin_blind;
+  union GNUNET_CRYPTO_BlindingSecretP coin_blind;
   struct TALER_ReservePublicKeyP reserve_pub;
   struct TALER_ReservePublicKeyP reserve_pub2;
   struct TALER_ReservePublicKeyP reserve_pub3;
@@ -1212,11 +1212,11 @@ run (void *cls)
   uint64_t reserve_out_serial_id;
   uint64_t melt_serial_id;
   struct TALER_PlanchetMasterSecretP ps;
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
   struct TALER_ExchangeWithdrawValues alg_values = {
     /* RSA is simpler, and for the DB there is no real difference between
        CS and RSA, just one should be used, so we use RSA */
-    .cipher = TALER_DENOMINATION_RSA
+    .cipher = GNUNET_CRYPTO_BSA_RSA
   };
 
   memset (&deposit,
@@ -1667,7 +1667,7 @@ run (void *cls)
       new_denom_pubs[cnt] = new_dkp[cnt]->pub;
       ccoin = &revealed_coins[cnt];
       bp = &ccoin->blinded_planchet;
-      bp->cipher = TALER_DENOMINATION_RSA;
+      bp->cipher = GNUNET_CRYPTO_BSA_RSA;
       rp = &bp->details.rsa_blinded_planchet;
       rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
         GNUNET_CRYPTO_QUALITY_WEAK,
@@ -1759,7 +1759,7 @@ run (void *cls)
   {
     struct GNUNET_TIME_Timestamp recoup_timestamp
       = GNUNET_TIME_timestamp_get ();
-    union TALER_DenominationBlindingKeyP coin_bks;
+    union GNUNET_CRYPTO_BlindingSecretP coin_bks;
     uint64_t new_known_coin_id;
     struct TALER_CoinPublicInfo new_coin;
     struct TALER_DenominationHashP dph;
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index bbf0520e..06bf7f51 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -609,24 +609,6 @@ enum TALER_MerchantConfirmationAlgorithm
 };
 
 
-/**
- * @brief Type of blinding keys for Taler.
- * must be 32 bytes (DB)
- */
-union TALER_DenominationBlindingKeyP
-{
-  /**
-   * Clause Schnorr Signatures have 2 blinding secrets, each containing two 
unpredictable values. (must be 32 bytes)
-   */
-  struct GNUNET_CRYPTO_CsNonce nonce;
-
-  /**
-   * Taler uses RSA for blind signatures.
-   */
-  struct GNUNET_CRYPTO_RsaBlindingKeySecret rsa_bks;
-};
-
-
 /**
  * Commitment value for the refresh protocol.
  * See #TALER_refresh_get_commitment().
@@ -1149,6 +1131,17 @@ void
 TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa,
                     struct TALER_RsaPubHashP *h_rsa);
 
+
+/**
+ * Return the alg value singleton for creation of
+ * blinding secrets for RSA.
+ *
+ * @return singleton to use for RSA blinding
+ */
+const struct TALER_ExchangeWithdrawValues *
+TALER_denom_ewv_rsa_singleton (void);
+
+
 /**
  * Hash @a cs.
  *
@@ -1160,113 +1153,31 @@ TALER_cs_pub_hash (const struct 
GNUNET_CRYPTO_CsPublicKey *cs,
                    struct TALER_CsPubHashP *h_cs);
 
 
-/**
- * Types of public keys used for denominations in Taler.
- * FIXME: rename to BlindCipher
- */
-enum TALER_DenominationCipher
-{
-
-  /**
-   * Invalid type of signature.
-   */
-  TALER_DENOMINATION_INVALID = 0,
-
-  /**
-   * RSA blind signature.
-   */
-  TALER_DENOMINATION_RSA = 1,
-
-  /**
-   * Clause Blind Schnorr signature.
-   */
-  TALER_DENOMINATION_CS = 2
-};
-
-
 /**
  * @brief Type of (unblinded) coin signatures for Taler.
- * FIXME: rename to BlindSignature
  */
 struct TALER_DenominationSignature
 {
-
   /**
-   * Type of the signature.
+   * Denominations use blind signatures.
    */
-  enum TALER_DenominationCipher cipher;
-
-  /**
-   * Details, depending on @e cipher.
-   */
-  union
-  {
-    /**
-     * If we use #TALER_DENOMINATION_CS in @a cipher.
-     */
-    struct GNUNET_CRYPTO_CsSignature cs_signature;
-
-    /**
-     * If we use #TALER_DENOMINATION_RSA in @a cipher.
-     */
-    struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
-
-  } details;
-
+  struct GNUNET_CRYPTO_UnblindedSignature *unblinded_sig;
 };
 
-/**
- * The Sign Answer for Clause Blind Schnorr signature.
- * The sign operation returns a parameter @param b and the signature
- * scalar @param s_scalar.
- */
-struct TALER_BlindedDenominationCsSignAnswer
-{
-  /**
-   * To make ROS problem harder, the signer chooses an unpredictable b and 
only calculates signature of c_b
-   */
-  unsigned int b;
-
-  /**
-   * The blinded s scalar calculated from c_b
-   */
-  struct GNUNET_CRYPTO_CsBlindS s_scalar;
-};
 
 /**
  * @brief Type for *blinded* denomination signatures for Taler.
  * Must be unblinded before it becomes valid.
- * FIXME: rename to BlindedSignature
  */
 struct TALER_BlindedDenominationSignature
 {
-
-  /**
-   * Type of the signature.
-   */
-  enum TALER_DenominationCipher cipher;
-
   /**
-   * Details, depending on @e cipher.
+   * Denominations use blind signatures.
    */
-  union
-  {
-    /**
-     * If we use #TALER_DENOMINATION_CS in @a cipher.
-     * At this point only the blinded s scalar is used.
-     * The final signature consisting of r,s is built after unblinding.
-     */
-    struct TALER_BlindedDenominationCsSignAnswer blinded_cs_answer;
-
-    /**
-     * If we use #TALER_DENOMINATION_RSA in @a cipher.
-     */
-    struct GNUNET_CRYPTO_RsaSignature *blinded_rsa_signature;
-
-  } details;
-
+  struct GNUNET_CRYPTO_BlindedSignature *blinded_sig;
 };
 
+
 /* *************** Age Restriction *********************************** */
 
 /*
@@ -1320,164 +1231,44 @@ struct TALER_AgeAttestation
 
 /**
  * @brief Type of public signing keys for verifying blindly signed coins.
- * FIXME: rename to BlindPublicKey
  */
 struct TALER_DenominationPublicKey
 {
 
-  /**
-   * Type of the public key.
-   */
-  enum TALER_DenominationCipher cipher;
-
   /**
    * Age restriction mask used for the key.
    */
   struct TALER_AgeMask age_mask;
 
   /**
-   * Details, depending on @e cipher.
+   * Type of the public key.
    */
-  union
-  {
-    /**
-     * If we use #TALER_DENOMINATION_CS in @a cipher.
-     */
-    struct GNUNET_CRYPTO_CsPublicKey cs_public_key;
+  struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub_key;
 
-    /**
-     * If we use #TALER_DENOMINATION_RSA in @a cipher.
-     */
-    struct GNUNET_CRYPTO_RsaPublicKey *rsa_public_key;
-
-  } details;
 };
 
 
 /**
  * @brief Type of private signing keys for blind signing of coins.
- * FIXME: rename to BlindPrivateKey
  */
 struct TALER_DenominationPrivateKey
 {
 
-  /**
-   * Type of the public key.
-   */
-  enum TALER_DenominationCipher cipher;
-
-  /**
-   * Details, depending on @e cipher.
-   */
-  union
-  {
-    /**
-     * If we use #TALER_DENOMINATION_CS in @a cipher.
-     */
-    struct GNUNET_CRYPTO_CsPrivateKey cs_private_key;
-
-    /**
-     * If we use #TALER_DENOMINATION_RSA in @a cipher.
-     */
-    struct GNUNET_CRYPTO_RsaPrivateKey *rsa_private_key;
-
-  } details;
-};
-
-/**
- * @brief RSA Parameters to create blinded signature
- *
- * FIXME: rename to BlindedMessage or so???
- */
-struct TALER_BlindedRsaPlanchet
-{
-  /**
-   * Blinded message to be signed
-   * Note: is malloc()'ed!
-   */
-  void *blinded_msg;
-
-  /**
-   * Size of the @e blinded_msg to be signed.
-   */
-  size_t blinded_msg_size;
-};
+  struct GNUNET_CRYPTO_BlindSignPrivateKey *bsign_priv_key;
 
-
-/**
- * Withdraw nonce for CS denominations
- */
-struct TALER_CsNonce
-{
-  /**
-   * 32 bit nonce to include in withdrawals when using CS.
-   */
-  struct GNUNET_CRYPTO_CsNonce nonce;
 };
 
 
 /**
- * @brief CS Parameters to create blinded signature
- */
-struct TALER_BlindedCsPlanchet
-{
-  /**
-   * The Clause Schnorr c_0 and c_1 containing the blinded message
-   */
-  struct GNUNET_CRYPTO_CsC c[2];
-
-  /**
-   * Public nonce.
-   */
-  struct TALER_CsNonce nonce;
-};
-
-
-/**
- * @brief Type including Parameters to create blinded signature
- * FIXME: rename to BlindedXXX
+ * @brief Blinded planchet send to exchange for blind signing.
  */
 struct TALER_BlindedPlanchet
 {
   /**
-   * Type of the sign blinded message
-   */
-  enum TALER_DenominationCipher cipher;
-
-  /**
-   * Details, depending on @e cipher.
+   * A blinded message.
    */
-  union
-  {
-    /**
-     * If we use #TALER_DENOMINATION_CS in @a cipher.
-     */
-    struct TALER_BlindedCsPlanchet cs_blinded_planchet;
-
-    /**
-     * If we use #TALER_DENOMINATION_RSA in @a cipher.
-     */
-    struct TALER_BlindedRsaPlanchet rsa_blinded_planchet;
-
-  } details;
-};
-
-
-/**
- * Pair of Public R values for Cs denominations
- */
-struct TALER_DenominationCSPublicRPairP
-{
-  struct GNUNET_CRYPTO_CsRPublic r_pub[2];
-};
+  struct GNUNET_CRYPTO_BlindedMessage *blinded_message;
 
-
-/**
- * Secret r for Cs denominations
- */
-struct TALER_DenominationCSPrivateRPairP
-{
-  struct GNUNET_CRYPTO_CsRSecret r[2];
 };
 
 
@@ -1548,41 +1339,18 @@ struct TALER_TrackTransferDetails
 
 
 /**
- * @brief Type of algorithm specific Values for withdrawal
- * FIXME: rename to BlindedInputValues or so???
+ * @brief Inputs needed from the exchange for blind signing.
  */
 struct TALER_ExchangeWithdrawValues
 {
 
   /**
-   * Type of the signature.
-   */
-  enum TALER_DenominationCipher cipher;
-
-  /**
-   * Details, depending on @e cipher.
+   * Input values.
    */
-  union
-  {
-    /**
-     * If we use #TALER_DENOMINATION_CS in @a cipher.
-     */
-    struct TALER_DenominationCSPublicRPairP cs_values;
-
-  } details;
-
+  struct GNUNET_CRYPTO_BlindingInputValues *blinding_inputs;
 };
 
 
-/**
- * Free internals of @a denom_pub, but not @a denom_pub itself.
- *
- * @param[in] denom_pub key to free
- */
-void
-TALER_denom_pub_free (struct TALER_DenominationPublicKey *denom_pub);
-
-
 /**
  * Create private key for a Taler coin.
  * @param ps planchet secret to derive coin priv key
@@ -1605,7 +1373,7 @@ TALER_planchet_setup_coin_priv (
 void
 TALER_cs_withdraw_nonce_derive (
   const struct TALER_PlanchetMasterSecretP *ps,
-  struct TALER_CsNonce *nonce);
+  struct GNUNET_CRYPTO_CsSessionNonce *nonce);
 
 
 /**
@@ -1620,13 +1388,13 @@ void
 TALER_cs_refresh_nonce_derive (
   const struct TALER_RefreshMasterSecretP *rms,
   uint32_t idx,
-  struct TALER_CsNonce *nonce);
+  struct GNUNET_CRYPTO_CsSessionNonce *nonce);
 
 
 /**
  * Initialize denomination public-private key pair.
  *
- * For #TALER_DENOMINATION_RSA, an additional "unsigned int"
+ * For #GNUNET_CRYPTO_BSA_RSA, an additional "unsigned int"
  * argument with the number of bits for 'n' (e.g. 2048) must
  * be passed.
  *
@@ -1639,10 +1407,19 @@ TALER_cs_refresh_nonce_derive (
 enum GNUNET_GenericReturnValue
 TALER_denom_priv_create (struct TALER_DenominationPrivateKey *denom_priv,
                          struct TALER_DenominationPublicKey *denom_pub,
-                         enum TALER_DenominationCipher cipher,
+                         enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher,
                          ...);
 
 
+/**
+ * Free internals of @a denom_pub, but not @a denom_pub itself.
+ *
+ * @param[in] denom_pub key to free
+ */
+void
+TALER_denom_pub_free (struct TALER_DenominationPublicKey *denom_pub);
+
+
 /**
  * Free internals of @a denom_priv, but not @a denom_priv itself.
  *
@@ -1670,6 +1447,8 @@ TALER_denom_sig_free (struct TALER_DenominationSignature 
*denom_sig);
  *
  * @param dk denomination public key to blind for
  * @param coin_bks blinding secret to use
+ * @param nonce nonce used to derive session values,
+ *        could be NULL for ciphers that do not use it
  * @param age_commitment_hash hash of the age commitment to be used for the 
coin. NULL if no commitment is made.
  * @param coin_pub public key of the coin to blind
  * @param alg_values algorithm specific values to blind the planchet
@@ -1679,7 +1458,8 @@ TALER_denom_sig_free (struct TALER_DenominationSignature 
*denom_sig);
  */
 enum GNUNET_GenericReturnValue
 TALER_denom_blind (const struct TALER_DenominationPublicKey *dk,
-                   const union TALER_DenominationBlindingKeyP *coin_bks,
+                   const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
+                   const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
                    const struct TALER_AgeCommitmentHash *age_commitment_hash,
                    const struct TALER_CoinSpendPublicKeyP *coin_pub,
                    const struct TALER_ExchangeWithdrawValues *alg_values,
@@ -1718,7 +1498,7 @@ enum GNUNET_GenericReturnValue
 TALER_denom_sig_unblind (
   struct TALER_DenominationSignature *denom_sig,
   const struct TALER_BlindedDenominationSignature *bdenom_sig,
-  const union TALER_DenominationBlindingKeyP *bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *bks,
   const struct TALER_CoinPubHashP *c_hash,
   const struct TALER_ExchangeWithdrawValues *alg_values,
   const struct TALER_DenominationPublicKey *denom_pub);
@@ -1832,19 +1612,6 @@ TALER_blinded_planchet_cmp (
   const struct TALER_BlindedPlanchet *bp2);
 
 
-/**
- * Obtain denomination public key from a denomination private key.
- *
- * @param denom_priv private key to convert
- * @param age_mask age mask to be applied
- * @param[out] denom_pub where to return the public key
- */
-void
-TALER_denom_priv_to_pub (const struct TALER_DenominationPrivateKey *denom_priv,
-                         const struct TALER_AgeMask age_mask,
-                         struct TALER_DenominationPublicKey *denom_pub);
-
-
 /**
  * Verify signature made with a denomination public key
  * over a coin.
@@ -2160,7 +1927,7 @@ void
 TALER_planchet_blinding_secret_create (
   const struct TALER_PlanchetMasterSecretP *ps,
   const struct TALER_ExchangeWithdrawValues *alg_values,
-  union TALER_DenominationBlindingKeyP *bks);
+  union GNUNET_CRYPTO_BlindingSecretP *bks);
 
 
 /**
@@ -2169,6 +1936,7 @@ TALER_planchet_blinding_secret_create (
  * @param dk denomination key for the coin to be created
  * @param alg_values algorithm specific values
  * @param bks blinding secrets
+ * @param nonce session nonce used to get @a alg_values
  * @param coin_priv coin private key
  * @param ach hash of age commitment to bind to this coin, maybe NULL
  * @param[out] c_hash set to the hash of the public key of the coin (needed 
later)
@@ -2180,7 +1948,8 @@ TALER_planchet_blinding_secret_create (
 enum GNUNET_GenericReturnValue
 TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk,
                         const struct TALER_ExchangeWithdrawValues *alg_values,
-                        const union TALER_DenominationBlindingKeyP *bks,
+                        const union GNUNET_CRYPTO_BlindingSecretP *bks,
+                        const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
                         const struct TALER_CoinSpendPrivateKeyP *coin_priv,
                         const struct TALER_AgeCommitmentHash *ach,
                         struct TALER_CoinPubHashP *c_hash,
@@ -2224,7 +1993,7 @@ enum GNUNET_GenericReturnValue
 TALER_planchet_to_coin (
   const struct TALER_DenominationPublicKey *dk,
   const struct TALER_BlindedDenominationSignature *blind_sig,
-  const union TALER_DenominationBlindingKeyP *bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *bks,
   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   const struct TALER_AgeCommitmentHash *ach,
   const struct TALER_CoinPubHashP *c_hash,
@@ -2540,7 +2309,7 @@ typedef void
   struct GNUNET_TIME_Timestamp start_time,
   struct GNUNET_TIME_Relative validity_duration,
   const struct TALER_RsaPubHashP *h_rsa,
-  const struct TALER_DenominationPublicKey *denom_pub,
+  struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub,
   const struct TALER_SecurityModulePublicKeyP *sm_pub,
   const struct TALER_SecurityModuleSignatureP *sm_sig);
 
@@ -2641,9 +2410,9 @@ TALER_CRYPTO_helper_rsa_sign (
 enum TALER_ErrorCode
 TALER_CRYPTO_helper_rsa_batch_sign (
   struct TALER_CRYPTO_RsaDenominationHelper *dh,
-  const struct TALER_CRYPTO_RsaSignRequest *rsrs,
   unsigned int rsrs_length,
-  struct TALER_BlindedDenominationSignature *bss);
+  const struct TALER_CRYPTO_RsaSignRequest rsrs[static rsrs_length],
+  struct TALER_BlindedDenominationSignature bss[static rsrs_length]);
 
 
 /**
@@ -2697,7 +2466,7 @@ struct TALER_CRYPTO_CsDenominationHelper;
  * @param validity_duration how long does the key remain available for signing;
  *                 zero if the key has been revoked or purged
  * @param h_cs hash of the CS @a denom_pub that is available (or was purged)
- * @param denom_pub the public key itself, NULL if the key was revoked or 
purged
+ * @param bsign_pub the public key itself, NULL if the key was revoked or 
purged
  * @param sm_pub public key of the security module, NULL if the key was 
revoked or purged
  * @param sm_sig signature from the security module, NULL if the key was 
revoked or purged
  *               The signature was already verified against @a sm_pub.
@@ -2709,7 +2478,7 @@ typedef void
   struct GNUNET_TIME_Timestamp start_time,
   struct GNUNET_TIME_Relative validity_duration,
   const struct TALER_CsPubHashP *h_cs,
-  const struct TALER_DenominationPublicKey *denom_pub,
+  struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub,
   const struct TALER_SecurityModulePublicKeyP *sm_pub,
   const struct TALER_SecurityModuleSignatureP *sm_sig);
 
@@ -2755,7 +2524,8 @@ struct TALER_CRYPTO_CsSignRequest
   /**
    * Blinded planchet containing c and the nonce.
    */
-  const struct TALER_BlindedCsPlanchet *blinded_planchet;
+  const struct GNUNET_CRYPTO_CsBlindedMessage *blinded_planchet;
+
 };
 
 
@@ -2801,10 +2571,10 @@ TALER_CRYPTO_helper_cs_sign (
 enum TALER_ErrorCode
 TALER_CRYPTO_helper_cs_batch_sign (
   struct TALER_CRYPTO_CsDenominationHelper *dh,
-  const struct TALER_CRYPTO_CsSignRequest *reqs,
   unsigned int reqs_length,
+  const struct TALER_CRYPTO_CsSignRequest reqs[static reqs_length],
   bool for_melt,
-  struct TALER_BlindedDenominationSignature *bss);
+  struct TALER_BlindedDenominationSignature bss[static reqs_length]);
 
 
 /**
@@ -2839,9 +2609,9 @@ struct TALER_CRYPTO_CsDeriveRequest
   const struct TALER_CsPubHashP *h_cs;
 
   /**
-   * Nonce to use.
+   * Nonce to use for the /csr request.
    */
-  const struct TALER_CsNonce *nonce;
+  const struct GNUNET_CRYPTO_CsSessionNonce *nonce;
 };
 
 
@@ -2866,7 +2636,7 @@ TALER_CRYPTO_helper_cs_r_derive (
   struct TALER_CRYPTO_CsDenominationHelper *dh,
   const struct TALER_CRYPTO_CsDeriveRequest *cdr,
   bool for_melt,
-  struct TALER_DenominationCSPublicRPairP *crp);
+  struct GNUNET_CRYPTO_CSPublicRPairP *crp);
 
 
 /**
@@ -2879,8 +2649,8 @@ TALER_CRYPTO_helper_cs_r_derive (
  * differences in the signature counters.  Retrying in this case may work.
  *
  * @param dh helper to process connection
- * @param cdrs array with derivation input data
  * @param cdrs_length length of the @a cdrs array
+ * @param cdrs array with derivation input data
  * @param for_melt true if this is for a melt operation
  * @param[out] crps array set to the pair of R values, must be of length @a 
cdrs_length
  * @return set to the error code (or #TALER_EC_NONE on success)
@@ -2888,10 +2658,10 @@ TALER_CRYPTO_helper_cs_r_derive (
 enum TALER_ErrorCode
 TALER_CRYPTO_helper_cs_r_batch_derive (
   struct TALER_CRYPTO_CsDenominationHelper *dh,
-  const struct TALER_CRYPTO_CsDeriveRequest *cdrs,
   unsigned int cdrs_length,
+  const struct TALER_CRYPTO_CsDeriveRequest cdrs[static cdrs_length],
   bool for_melt,
-  struct TALER_DenominationCSPublicRPairP *crps);
+  struct GNUNET_CRYPTO_CSPublicRPairP crps[static cdrs_length]);
 
 
 /**
@@ -3805,7 +3575,7 @@ TALER_exchange_melt_confirmation_verify (
 enum GNUNET_GenericReturnValue
 TALER_wallet_recoup_verify (
   const struct TALER_DenominationHashP *h_denom_pub,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   const struct TALER_CoinSpendSignatureP *coin_sig);
 
@@ -3821,7 +3591,7 @@ TALER_wallet_recoup_verify (
 void
 TALER_wallet_recoup_sign (
   const struct TALER_DenominationHashP *h_denom_pub,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   struct TALER_CoinSpendSignatureP *coin_sig);
 
@@ -3838,7 +3608,7 @@ TALER_wallet_recoup_sign (
 enum GNUNET_GenericReturnValue
 TALER_wallet_recoup_refresh_verify (
   const struct TALER_DenominationHashP *h_denom_pub,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   const struct TALER_CoinSpendSignatureP *coin_sig);
 
@@ -3854,7 +3624,7 @@ TALER_wallet_recoup_refresh_verify (
 void
 TALER_wallet_recoup_refresh_sign (
   const struct TALER_DenominationHashP *h_denom_pub,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   struct TALER_CoinSpendSignatureP *coin_sig);
 
@@ -6067,7 +5837,7 @@ struct TALER_DenominationGroup
   /**
    * Cipher used for the denomination.
    */
-  enum TALER_DenominationCipher cipher;
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher;
 
   /**
    * Age mask for the denomiation.
diff --git a/src/include/taler_exchange_service.h 
b/src/include/taler_exchange_service.h
index 44f43367..fb0a578a 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -1558,7 +1558,7 @@ TALER_EXCHANGE_csr_withdraw (
   struct GNUNET_CURL_Context *curl_ctx,
   const char *exchange_url,
   const struct TALER_EXCHANGE_DenomPublicKey *pk,
-  const struct TALER_CsNonce *nonce,
+  const struct GNUNET_CRYPTO_CsSessionNonce *nonce,
   TALER_EXCHANGE_CsRWithdrawCallback res_cb,
   void *res_cb_cls);
 
@@ -1698,7 +1698,7 @@ struct TALER_EXCHANGE_CoinHistoryEntry
     {
       struct TALER_ReservePublicKeyP reserve_pub;
       struct GNUNET_TIME_Timestamp timestamp;
-      union TALER_DenominationBlindingKeyP coin_bks;
+      union GNUNET_CRYPTO_BlindingSecretP coin_bks;
       struct TALER_ExchangePublicKeyP exchange_pub;
       struct TALER_ExchangeSignatureP exchange_sig;
       struct TALER_CoinSpendSignatureP coin_sig;
@@ -1707,7 +1707,7 @@ struct TALER_EXCHANGE_CoinHistoryEntry
     struct
     {
       struct TALER_CoinSpendPublicKeyP old_coin_pub;
-      union TALER_DenominationBlindingKeyP coin_bks;
+      union GNUNET_CRYPTO_BlindingSecretP coin_bks;
       struct GNUNET_TIME_Timestamp timestamp;
       struct TALER_ExchangePublicKeyP exchange_pub;
       struct TALER_ExchangeSignatureP exchange_sig;
@@ -2487,7 +2487,7 @@ struct TALER_EXCHANGE_PrivateCoinDetails
    * Value used to blind the key for the signature.
    * Needed for recoup operations.
    */
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
 
   /**
    * Signature over the coin.
@@ -2890,7 +2890,7 @@ struct TALER_EXCHANGE_AgeWithdrawCoinPrivateDetails
    * Value used to blind the key for the signature.
    * Needed for recoup operations.
    */
-  union TALER_DenominationBlindingKeyP blinding_key;
+  union GNUNET_CRYPTO_BlindingSecretP blinding_key;
 
   /**
    * The age commitment, proof for the coin, derived from the
@@ -3464,7 +3464,7 @@ struct TALER_EXCHANGE_RevealedCoinInfo
   /**
    * Blinding keys used to blind the fresh coin.
    */
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
 
   /**
    * Signature affirming the validity of the coin.
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 252c27a7..9d541ac1 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -569,7 +569,7 @@ struct TALER_EXCHANGEDB_TableData
     {
       struct TALER_CoinSpendPublicKeyP coin_pub;
       struct TALER_CoinSpendSignatureP coin_sig;
-      union TALER_DenominationBlindingKeyP coin_blind;
+      union GNUNET_CRYPTO_BlindingSecretP coin_blind;
       struct TALER_Amount amount;
       struct GNUNET_TIME_Timestamp timestamp;
       uint64_t reserve_out_serial_id;
@@ -580,7 +580,7 @@ struct TALER_EXCHANGEDB_TableData
       uint64_t known_coin_id;
       struct TALER_CoinSpendPublicKeyP coin_pub;
       struct TALER_CoinSpendSignatureP coin_sig;
-      union TALER_DenominationBlindingKeyP coin_blind;
+      union GNUNET_CRYPTO_BlindingSecretP coin_blind;
       struct TALER_Amount amount;
       struct GNUNET_TIME_Timestamp timestamp;
       uint64_t rrc_serial;
@@ -1278,7 +1278,7 @@ struct TALER_EXCHANGEDB_Recoup
    * Blinding factor supplied to prove to the exchange that
    * the coin came from this reserve.
    */
-  union TALER_DenominationBlindingKeyP coin_blind;
+  union GNUNET_CRYPTO_BlindingSecretP coin_blind;
 
   /**
    * Signature of the coin of type
@@ -1332,7 +1332,7 @@ struct TALER_EXCHANGEDB_RecoupListEntry
    * Blinding factor supplied to prove to the exchange that
    * the coin came from this reserve.
    */
-  union TALER_DenominationBlindingKeyP coin_blind;
+  union GNUNET_CRYPTO_BlindingSecretP coin_blind;
 
   /**
    * Signature of the coin of type
@@ -1380,7 +1380,7 @@ struct TALER_EXCHANGEDB_RecoupRefreshListEntry
    * Blinding factor supplied to prove to the exchange that
    * the coin came from this @e old_coin_pub.
    */
-  union TALER_DenominationBlindingKeyP coin_blind;
+  union GNUNET_CRYPTO_BlindingSecretP coin_blind;
 
   /**
    * Signature of the coin of type
@@ -2423,9 +2423,9 @@ struct TALER_EXCHANGEDB_LinkList
   struct TALER_CoinSpendSignatureP orig_coin_link_sig;
 
   /**
-   * CS nonce, if cipher is CS.
+   * Session nonce, if cipher has one.
    */
-  struct TALER_CsNonce nonce;
+  union GNUNET_CRYPTO_BlindSessionNonce nonce;
 
   /**
    * Offset that generated this coin in the refresh
@@ -3245,7 +3245,7 @@ typedef enum GNUNET_GenericReturnValue
   const struct TALER_CoinPublicInfo *coin,
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_CoinSpendSignatureP *coin_sig,
-  const union TALER_DenominationBlindingKeyP *coin_blind);
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_blind);
 
 
 /**
@@ -3275,7 +3275,7 @@ typedef enum GNUNET_GenericReturnValue
   const struct TALER_CoinPublicInfo *coin,
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_CoinSpendSignatureP *coin_sig,
-  const union TALER_DenominationBlindingKeyP *coin_blind);
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_blind);
 
 
 /**
@@ -3388,7 +3388,7 @@ typedef void
   uint64_t rowid,
   const struct TALER_CoinPublicInfo *coin,
   const struct TALER_CoinSpendSignatureP *coin_sig,
-  const union TALER_DenominationBlindingKeyP *coin_blind,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_blind,
   const struct TALER_BlindedCoinHashP *h_blinded_ev,
   const struct TALER_Amount *amount);
 
@@ -3855,7 +3855,7 @@ struct TALER_EXCHANGEDB_Plugin
    */
   enum GNUNET_DB_QueryStatus
   (*lock_nonce)(void *cls,
-                const struct TALER_CsNonce *nonce,
+                const struct GNUNET_CRYPTO_CsSessionNonce *nonce,
                 const struct TALER_DenominationHashP *denom_pub_hash,
                 const union TALER_EXCHANGEDB_NonceLockTargetP *target);
 
@@ -3936,7 +3936,7 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*do_batch_withdraw_insert)(
     void *cls,
-    const struct TALER_CsNonce *nonce,
+    const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
     const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable,
     struct GNUNET_TIME_Timestamp now,
     uint64_t ruuid,
@@ -4100,7 +4100,7 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*cs_refreshes_reveal)(
     void *cls,
-    const struct TALER_CsNonce *nonce,
+    const struct GNUNET_CRYPTO_CsSessionNonce *nonce,
     const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
     unsigned int num_fresh_coins,
     struct TALER_EXCHANGEDB_CsRevealFreshCoinData *crfcds);
@@ -4153,7 +4153,7 @@ struct TALER_EXCHANGEDB_Plugin
     void *cls,
     const struct TALER_ReservePublicKeyP *reserve_pub,
     uint64_t reserve_out_serial_id,
-    const union TALER_DenominationBlindingKeyP *coin_bks,
+    const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
     const struct TALER_CoinSpendPublicKeyP *coin_pub,
     uint64_t known_coin_id,
     const struct TALER_CoinSpendSignatureP *coin_sig,
@@ -4183,7 +4183,7 @@ struct TALER_EXCHANGEDB_Plugin
     void *cls,
     const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
     uint64_t rrc_serial,
-    const union TALER_DenominationBlindingKeyP *coin_bks,
+    const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
     const struct TALER_CoinSpendPublicKeyP *coin_pub,
     uint64_t known_coin_id,
     const struct TALER_CoinSpendSignatureP *coin_sig,
diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h
index a8da05e4..1a146670 100644
--- a/src/include/taler_json_lib.h
+++ b/src/include/taler_json_lib.h
@@ -366,7 +366,8 @@ TALER_JSON_spec_denom_pub (const char *field,
  */
 struct GNUNET_JSON_Specification
 TALER_JSON_spec_denom_pub_cipher (const char *field,
-                                  enum TALER_DenominationCipher cipher,
+                                  enum GNUNET_CRYPTO_BlindSignatureAlgorithm
+                                  cipher,
                                   struct TALER_DenominationPublicKey *pk);
 
 
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index 72d70d00..13696718 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -2732,7 +2732,7 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait 
*traits,
   op (refund_deadline, const struct GNUNET_TIME_Timestamp)              \
   op (exchange_pub, const struct TALER_ExchangePublicKeyP)              \
   op (exchange_sig, const struct TALER_ExchangeSignatureP)              \
-  op (blinding_key, const union TALER_DenominationBlindingKeyP)         \
+  op (blinding_key, const union GNUNET_CRYPTO_BlindingSecretP)         \
   op (h_blinded_coin, const struct TALER_BlindedCoinHashP)
 
 TALER_TESTING_SIMPLE_TRAITS (TALER_TESTING_MAKE_DECL_SIMPLE_TRAIT)
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
index 6c960353..57c42e48 100644
--- a/src/json/json_helper.c
+++ b/src/json/json_helper.c
@@ -32,20 +32,20 @@
  * @param cipher_s input string
  * @return numeric cipher value
  */
-static enum TALER_DenominationCipher
+static enum GNUNET_CRYPTO_BlindSignatureAlgorithm
 string_to_cipher (const char *cipher_s)
 {
   if ((0 == strcasecmp (cipher_s,
                         "RSA")) ||
       (0 == strcasecmp (cipher_s,
                         "RSA+age_restricted")))
-    return TALER_DENOMINATION_RSA;
+    return GNUNET_CRYPTO_BSA_RSA;
   if ((0 == strcasecmp (cipher_s,
                         "CS")) ||
       (0 == strcasecmp (cipher_s,
                         "CS+age_restricted")))
-    return TALER_DENOMINATION_CS;
-  return TALER_DENOMINATION_INVALID;
+    return GNUNET_CRYPTO_BSA_CS;
+  return GNUNET_CRYPTO_BSA_INVALID;
 }
 
 
@@ -324,7 +324,7 @@ parse_denomination_group (void *cls,
   }
 
   group->cipher = string_to_cipher (cipher);
-  if (TALER_DENOMINATION_INVALID == group->cipher)
+  if (GNUNET_CRYPTO_BSA_INVALID == group->cipher)
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
@@ -560,6 +560,7 @@ parse_denom_pub (void *cls,
                  struct GNUNET_JSON_Specification *spec)
 {
   struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
+  struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
   const char *cipher;
   bool age_mask_missing = false;
   struct GNUNET_JSON_Specification dspec[] = {
@@ -587,16 +588,19 @@ parse_denom_pub (void *cls,
 
   if (age_mask_missing)
     denom_pub->age_mask.bits = 0;
-
-  denom_pub->cipher = string_to_cipher (cipher);
-  switch (denom_pub->cipher)
+  bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
+  bsign_pub->rc = 1;
+  bsign_pub->cipher = string_to_cipher (cipher);
+  switch (bsign_pub->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     {
       struct GNUNET_JSON_Specification ispec[] = {
         GNUNET_JSON_spec_rsa_public_key (
           "rsa_public_key",
-          &denom_pub->details.rsa_public_key),
+          &bsign_pub->details.rsa_public_key),
         GNUNET_JSON_spec_end ()
       };
 
@@ -607,16 +611,18 @@ parse_denom_pub (void *cls,
                              &eline))
       {
         GNUNET_break_op (0);
+        GNUNET_free (bsign_pub);
         return GNUNET_SYSERR;
       }
+      denom_pub->bsign_pub_key = bsign_pub;
       return GNUNET_OK;
     }
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     {
       struct GNUNET_JSON_Specification ispec[] = {
         GNUNET_JSON_spec_fixed ("cs_public_key",
-                                &denom_pub->details.cs_public_key,
-                                sizeof (denom_pub->details.cs_public_key)),
+                                &bsign_pub->details.cs_public_key,
+                                sizeof (bsign_pub->details.cs_public_key)),
         GNUNET_JSON_spec_end ()
       };
 
@@ -627,14 +633,16 @@ parse_denom_pub (void *cls,
                              &eline))
       {
         GNUNET_break_op (0);
+        GNUNET_free (bsign_pub);
         return GNUNET_SYSERR;
       }
+      denom_pub->bsign_pub_key = bsign_pub;
       return GNUNET_OK;
     }
-  default:
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
   }
+  GNUNET_break_op (0);
+  GNUNET_free (bsign_pub);
+  return GNUNET_SYSERR;
 }
 
 
@@ -666,7 +674,7 @@ TALER_JSON_spec_denom_pub (const char *field,
     .ptr = pk
   };
 
-  pk->cipher = TALER_DENOMINATION_INVALID;
+  pk->bsign_pub_key = NULL;
   return ret;
 }
 
@@ -676,7 +684,7 @@ TALER_JSON_spec_denom_pub (const char *field,
  *
  * Depending on the cipher in cls, it parses the corresponding public key type.
  *
- * @param cls closure, enum TALER_DenominationCipher
+ * @param cls closure, enum GNUNET_CRYPTO_BlindSignatureAlgorithm
  * @param root the json object representing data
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
@@ -687,19 +695,25 @@ parse_denom_pub_cipher (void *cls,
                         struct GNUNET_JSON_Specification *spec)
 {
   struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
-  enum TALER_DenominationCipher cipher =
-    (enum TALER_DenominationCipher) (long) cls;
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher =
+    (enum GNUNET_CRYPTO_BlindSignatureAlgorithm) (long) cls;
+  struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
   const char *emsg;
   unsigned int eline;
 
+  bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
+  bsign_pub->cipher = cipher;
+  bsign_pub->rc = 1;
   switch (cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     {
       struct GNUNET_JSON_Specification ispec[] = {
         GNUNET_JSON_spec_rsa_public_key (
           "rsa_pub",
-          &denom_pub->details.rsa_public_key),
+          &bsign_pub->details.rsa_public_key),
         GNUNET_JSON_spec_end ()
       };
 
@@ -710,17 +724,18 @@ parse_denom_pub_cipher (void *cls,
                              &eline))
       {
         GNUNET_break_op (0);
+        GNUNET_free (bsign_pub);
         return GNUNET_SYSERR;
       }
-      denom_pub->cipher = cipher;
+      denom_pub->bsign_pub_key = bsign_pub;
       return GNUNET_OK;
     }
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     {
       struct GNUNET_JSON_Specification ispec[] = {
         GNUNET_JSON_spec_fixed ("cs_pub",
-                                &denom_pub->details.cs_public_key,
-                                sizeof (denom_pub->details.cs_public_key)),
+                                &bsign_pub->details.cs_public_key,
+                                sizeof (bsign_pub->details.cs_public_key)),
         GNUNET_JSON_spec_end ()
       };
 
@@ -731,22 +746,23 @@ parse_denom_pub_cipher (void *cls,
                              &eline))
       {
         GNUNET_break_op (0);
+        GNUNET_free (bsign_pub);
         return GNUNET_SYSERR;
       }
-      denom_pub->cipher = cipher;
+      denom_pub->bsign_pub_key = bsign_pub;
       return GNUNET_OK;
     }
-  default:
-    GNUNET_break_op (0);
-    denom_pub->cipher = 0;
-    return GNUNET_SYSERR;
   }
+  GNUNET_break_op (0);
+  GNUNET_free (bsign_pub);
+  return GNUNET_SYSERR;
 }
 
 
 struct GNUNET_JSON_Specification
 TALER_JSON_spec_denom_pub_cipher (const char *field,
-                                  enum TALER_DenominationCipher cipher,
+                                  enum GNUNET_CRYPTO_BlindSignatureAlgorithm
+                                  cipher,
                                   struct TALER_DenominationPublicKey *pk)
 {
   struct GNUNET_JSON_Specification ret = {
@@ -775,6 +791,7 @@ parse_denom_sig (void *cls,
                  struct GNUNET_JSON_Specification *spec)
 {
   struct TALER_DenominationSignature *denom_sig = spec->ptr;
+  struct GNUNET_CRYPTO_UnblindedSignature *unblinded_sig;
   const char *cipher;
   struct GNUNET_JSON_Specification dspec[] = {
     GNUNET_JSON_spec_string ("cipher",
@@ -794,15 +811,19 @@ parse_denom_sig (void *cls,
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  denom_sig->cipher = string_to_cipher (cipher);
-  switch (denom_sig->cipher)
+  unblinded_sig = GNUNET_new (struct GNUNET_CRYPTO_UnblindedSignature);
+  unblinded_sig->cipher = string_to_cipher (cipher);
+  unblinded_sig->rc = 1;
+  switch (unblinded_sig->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     {
       struct GNUNET_JSON_Specification ispec[] = {
         GNUNET_JSON_spec_rsa_signature (
           "rsa_signature",
-          &denom_sig->details.rsa_signature),
+          &unblinded_sig->details.rsa_signature),
         GNUNET_JSON_spec_end ()
       };
 
@@ -813,17 +834,21 @@ parse_denom_sig (void *cls,
                              &eline))
       {
         GNUNET_break_op (0);
+        GNUNET_free (unblinded_sig);
         return GNUNET_SYSERR;
       }
+      denom_sig->unblinded_sig = unblinded_sig;
       return GNUNET_OK;
     }
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     {
       struct GNUNET_JSON_Specification ispec[] = {
         GNUNET_JSON_spec_fixed_auto ("cs_signature_r",
-                                     &denom_sig->details.cs_signature.r_point),
+                                     &unblinded_sig->details.cs_signature.
+                                     r_point),
         GNUNET_JSON_spec_fixed_auto ("cs_signature_s",
-                                     
&denom_sig->details.cs_signature.s_scalar),
+                                     &unblinded_sig->details.cs_signature.
+                                     s_scalar),
         GNUNET_JSON_spec_end ()
       };
 
@@ -834,14 +859,16 @@ parse_denom_sig (void *cls,
                              &eline))
       {
         GNUNET_break_op (0);
+        GNUNET_free (unblinded_sig);
         return GNUNET_SYSERR;
       }
+      denom_sig->unblinded_sig = unblinded_sig;
       return GNUNET_OK;
     }
-  default:
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
   }
+  GNUNET_break_op (0);
+  GNUNET_free (unblinded_sig);
+  return GNUNET_SYSERR;
 }
 
 
@@ -873,7 +900,7 @@ TALER_JSON_spec_denom_sig (const char *field,
     .ptr = sig
   };
 
-  sig->cipher = TALER_DENOMINATION_INVALID;
+  sig->unblinded_sig = NULL;
   return ret;
 }
 
@@ -892,6 +919,7 @@ parse_blinded_denom_sig (void *cls,
                          struct GNUNET_JSON_Specification *spec)
 {
   struct TALER_BlindedDenominationSignature *denom_sig = spec->ptr;
+  struct GNUNET_CRYPTO_BlindedSignature *blinded_sig;
   const char *cipher;
   struct GNUNET_JSON_Specification dspec[] = {
     GNUNET_JSON_spec_string ("cipher",
@@ -911,15 +939,19 @@ parse_blinded_denom_sig (void *cls,
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  denom_sig->cipher = string_to_cipher (cipher);
-  switch (denom_sig->cipher)
+  blinded_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
+  blinded_sig->cipher = string_to_cipher (cipher);
+  blinded_sig->rc = 1;
+  switch (blinded_sig->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     {
       struct GNUNET_JSON_Specification ispec[] = {
         GNUNET_JSON_spec_rsa_signature (
           "blinded_rsa_signature",
-          &denom_sig->details.blinded_rsa_signature),
+          &blinded_sig->details.blinded_rsa_signature),
         GNUNET_JSON_spec_end ()
       };
 
@@ -930,17 +962,19 @@ parse_blinded_denom_sig (void *cls,
                              &eline))
       {
         GNUNET_break_op (0);
+        GNUNET_free (blinded_sig);
         return GNUNET_SYSERR;
       }
+      denom_sig->blinded_sig = blinded_sig;
       return GNUNET_OK;
     }
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     {
       struct GNUNET_JSON_Specification ispec[] = {
         GNUNET_JSON_spec_uint32 ("b",
-                                 &denom_sig->details.blinded_cs_answer.b),
+                                 &blinded_sig->details.blinded_cs_answer.b),
         GNUNET_JSON_spec_fixed_auto ("s",
-                                     &denom_sig->details.blinded_cs_answer.
+                                     &blinded_sig->details.blinded_cs_answer.
                                      s_scalar),
         GNUNET_JSON_spec_end ()
       };
@@ -952,15 +986,16 @@ parse_blinded_denom_sig (void *cls,
                              &eline))
       {
         GNUNET_break_op (0);
+        GNUNET_free (blinded_sig);
         return GNUNET_SYSERR;
       }
+      denom_sig->blinded_sig = blinded_sig;
       return GNUNET_OK;
     }
-    break;
-  default:
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
   }
+  GNUNET_break_op (0);
+  GNUNET_free (blinded_sig);
+  return GNUNET_SYSERR;
 }
 
 
@@ -993,7 +1028,7 @@ TALER_JSON_spec_blinded_denom_sig (
     .ptr = sig
   };
 
-  sig->cipher = TALER_DENOMINATION_INVALID;
+  sig->blinded_sig = NULL;
   return ret;
 }
 
@@ -1012,6 +1047,7 @@ parse_blinded_planchet (void *cls,
                         struct GNUNET_JSON_Specification *spec)
 {
   struct TALER_BlindedPlanchet *blinded_planchet = spec->ptr;
+  struct GNUNET_CRYPTO_BlindedMessage *blinded_message;
   const char *cipher;
   struct GNUNET_JSON_Specification dspec[] = {
     GNUNET_JSON_spec_string ("cipher",
@@ -1031,16 +1067,20 @@ parse_blinded_planchet (void *cls,
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  blinded_planchet->cipher = string_to_cipher (cipher);
-  switch (blinded_planchet->cipher)
+  blinded_message = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage);
+  blinded_message->rc = 1;
+  blinded_message->cipher = string_to_cipher (cipher);
+  switch (blinded_message->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     {
       struct GNUNET_JSON_Specification ispec[] = {
         GNUNET_JSON_spec_varsize (
           "rsa_blinded_planchet",
-          &blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
-          &blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size),
+          &blinded_message->details.rsa_blinded_message.blinded_msg,
+          &blinded_message->details.rsa_blinded_message.blinded_msg_size),
         GNUNET_JSON_spec_end ()
       };
 
@@ -1051,22 +1091,24 @@ parse_blinded_planchet (void *cls,
                              &eline))
       {
         GNUNET_break_op (0);
+        GNUNET_free (blinded_message);
         return GNUNET_SYSERR;
       }
+      blinded_planchet->blinded_message = blinded_message;
       return GNUNET_OK;
     }
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     {
       struct GNUNET_JSON_Specification ispec[] = {
         GNUNET_JSON_spec_fixed_auto (
           "cs_nonce",
-          &blinded_planchet->details.cs_blinded_planchet.nonce),
+          &blinded_message->details.cs_blinded_message.nonce),
         GNUNET_JSON_spec_fixed_auto (
           "cs_blinded_c0",
-          &blinded_planchet->details.cs_blinded_planchet.c[0]),
+          &blinded_message->details.cs_blinded_message.c[0]),
         GNUNET_JSON_spec_fixed_auto (
           "cs_blinded_c1",
-          &blinded_planchet->details.cs_blinded_planchet.c[1]),
+          &blinded_message->details.cs_blinded_message.c[1]),
         GNUNET_JSON_spec_end ()
       };
 
@@ -1077,15 +1119,16 @@ parse_blinded_planchet (void *cls,
                              &eline))
       {
         GNUNET_break_op (0);
+        GNUNET_free (blinded_message);
         return GNUNET_SYSERR;
       }
+      blinded_planchet->blinded_message = blinded_message;
       return GNUNET_OK;
     }
-    break;
-  default:
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
   }
+  GNUNET_break_op (0);
+  GNUNET_free (blinded_message);
+  return GNUNET_SYSERR;
 }
 
 
@@ -1117,7 +1160,7 @@ TALER_JSON_spec_blinded_planchet (const char *field,
     .ptr = blinded_planchet
   };
 
-  blinded_planchet->cipher = TALER_DENOMINATION_INVALID;
+  blinded_planchet->blinded_message = NULL;
   return ret;
 }
 
@@ -1136,6 +1179,7 @@ parse_exchange_withdraw_values (void *cls,
                                 struct GNUNET_JSON_Specification *spec)
 {
   struct TALER_ExchangeWithdrawValues *ewv = spec->ptr;
+  struct GNUNET_CRYPTO_BlindingInputValues *bi;
   const char *cipher;
   struct GNUNET_JSON_Specification dspec[] = {
     GNUNET_JSON_spec_string ("cipher",
@@ -1155,21 +1199,26 @@ parse_exchange_withdraw_values (void *cls,
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  ewv->cipher = string_to_cipher (cipher);
-  switch (ewv->cipher)
+  bi = GNUNET_new (struct GNUNET_CRYPTO_BlindingInputValues);
+  bi->cipher = string_to_cipher (cipher);
+  bi->rc = 1;
+  switch (bi->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
+    ewv->blinding_inputs = bi;
     return GNUNET_OK;
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     {
       struct GNUNET_JSON_Specification ispec[] = {
         GNUNET_JSON_spec_fixed (
           "r_pub_0",
-          &ewv->details.cs_values.r_pub[0],
+          &bi->details.cs_values.r_pub[0],
           sizeof (struct GNUNET_CRYPTO_CsRPublic)),
         GNUNET_JSON_spec_fixed (
           "r_pub_1",
-          &ewv->details.cs_values.r_pub[1],
+          &bi->details.cs_values.r_pub[1],
           sizeof (struct GNUNET_CRYPTO_CsRPublic)),
         GNUNET_JSON_spec_end ()
       };
@@ -1181,14 +1230,16 @@ parse_exchange_withdraw_values (void *cls,
                              &eline))
       {
         GNUNET_break_op (0);
+        GNUNET_free (bi);
         return GNUNET_SYSERR;
       }
+      ewv->blinding_inputs = bi;
       return GNUNET_OK;
     }
-  default:
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
   }
+  GNUNET_break_op (0);
+  GNUNET_free (bi);
+  return GNUNET_SYSERR;
 }
 
 
@@ -1203,7 +1254,7 @@ TALER_JSON_spec_exchange_withdraw_values (
     .ptr = ewv
   };
 
-  ewv->cipher = TALER_DENOMINATION_INVALID;
+  ewv->blinding_inputs = NULL;
   return ret;
 }
 
diff --git a/src/json/json_pack.c b/src/json/json_pack.c
index c6844c17..71c8db9d 100644
--- a/src/json/json_pack.c
+++ b/src/json/json_pack.c
@@ -101,37 +101,41 @@ TALER_JSON_pack_denom_pub (
   const char *name,
   const struct TALER_DenominationPublicKey *pk)
 {
+  const struct GNUNET_CRYPTO_BlindSignPublicKey *bsp;
   struct GNUNET_JSON_PackSpec ps = {
     .field_name = name,
   };
 
   if (NULL == pk)
     return ps;
-  switch (pk->cipher)
+  bsp = pk->bsign_pub_key;
+  switch (bsp->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     ps.object
       = GNUNET_JSON_PACK (
-          GNUNET_JSON_pack_string ("cipher", "RSA"),
+          GNUNET_JSON_pack_string ("cipher",
+                                   "RSA"),
           GNUNET_JSON_pack_uint64 ("age_mask",
                                    pk->age_mask.bits),
           GNUNET_JSON_pack_rsa_public_key ("rsa_public_key",
-                                           pk->details.rsa_public_key));
-    break;
-  case TALER_DENOMINATION_CS:
+                                           bsp->details.rsa_public_key));
+    return ps;
+  case GNUNET_CRYPTO_BSA_CS:
     ps.object
       = GNUNET_JSON_PACK (
-          GNUNET_JSON_pack_string ("cipher", "CS"),
+          GNUNET_JSON_pack_string ("cipher",
+                                   "CS"),
           GNUNET_JSON_pack_uint64 ("age_mask",
                                    pk->age_mask.bits),
           GNUNET_JSON_pack_data_varsize ("cs_public_key",
-                                         &pk->details.cs_public_key,
-                                         sizeof (pk->details.cs_public_key)));
-    break;
-  default:
-    GNUNET_assert (0);
+                                         &bsp->details.cs_public_key,
+                                         sizeof (bsp->details.cs_public_key)));
+    return ps;
   }
-
+  GNUNET_assert (0);
   return ps;
 }
 
@@ -141,33 +145,36 @@ TALER_JSON_pack_denom_sig (
   const char *name,
   const struct TALER_DenominationSignature *sig)
 {
+  const struct GNUNET_CRYPTO_UnblindedSignature *bs;
   struct GNUNET_JSON_PackSpec ps = {
     .field_name = name,
   };
 
   if (NULL == sig)
     return ps;
-  switch (sig->cipher)
+  bs = sig->unblinded_sig;
+  switch (bs->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     ps.object = GNUNET_JSON_PACK (
       GNUNET_JSON_pack_string ("cipher",
                                "RSA"),
       GNUNET_JSON_pack_rsa_signature ("rsa_signature",
-                                      sig->details.rsa_signature));
-    break;
-  case TALER_DENOMINATION_CS:
+                                      bs->details.rsa_signature));
+    return ps;
+  case GNUNET_CRYPTO_BSA_CS:
     ps.object = GNUNET_JSON_PACK (
       GNUNET_JSON_pack_string ("cipher",
                                "CS"),
       GNUNET_JSON_pack_data_auto ("cs_signature_r",
-                                  &sig->details.cs_signature.r_point),
+                                  &bs->details.cs_signature.r_point),
       GNUNET_JSON_pack_data_auto ("cs_signature_s",
-                                  &sig->details.cs_signature.s_scalar));
-    break;
-  default:
-    GNUNET_assert (0);
+                                  &bs->details.cs_signature.s_scalar));
+    return ps;
   }
+  GNUNET_assert (0);
   return ps;
 }
 
@@ -177,36 +184,39 @@ TALER_JSON_pack_exchange_withdraw_values (
   const char *name,
   const struct TALER_ExchangeWithdrawValues *ewv)
 {
+  const struct GNUNET_CRYPTO_BlindingInputValues *biv;
   struct GNUNET_JSON_PackSpec ps = {
     .field_name = name,
   };
 
   if (NULL == ewv)
     return ps;
-  switch (ewv->cipher)
+  biv = ewv->blinding_inputs;
+  switch (biv->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     ps.object = GNUNET_JSON_PACK (
       GNUNET_JSON_pack_string ("cipher",
                                "RSA"));
-    break;
-  case TALER_DENOMINATION_CS:
+    return ps;
+  case GNUNET_CRYPTO_BSA_CS:
     ps.object = GNUNET_JSON_PACK (
       GNUNET_JSON_pack_string ("cipher",
                                "CS"),
       GNUNET_JSON_pack_data_varsize (
         "r_pub_0",
-        &ewv->details.cs_values.r_pub[0],
+        &biv->details.cs_values.r_pub[0],
         sizeof(struct GNUNET_CRYPTO_CsRPublic)),
       GNUNET_JSON_pack_data_varsize (
         "r_pub_1",
-        &ewv->details.cs_values.r_pub[1],
+        &biv->details.cs_values.r_pub[1],
         sizeof(struct GNUNET_CRYPTO_CsRPublic))
       );
-    break;
-  default:
-    GNUNET_assert (0);
+    return ps;
   }
+  GNUNET_assert (0);
   return ps;
 }
 
@@ -216,33 +226,36 @@ TALER_JSON_pack_blinded_denom_sig (
   const char *name,
   const struct TALER_BlindedDenominationSignature *sig)
 {
+  const struct GNUNET_CRYPTO_BlindedSignature *bs;
   struct GNUNET_JSON_PackSpec ps = {
     .field_name = name,
   };
 
   if (NULL == sig)
     return ps;
-  switch (sig->cipher)
+  bs = sig->blinded_sig;
+  switch (bs->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     ps.object = GNUNET_JSON_PACK (
       GNUNET_JSON_pack_string ("cipher",
                                "RSA"),
       GNUNET_JSON_pack_rsa_signature ("blinded_rsa_signature",
-                                      sig->details.blinded_rsa_signature));
-    break;
-  case TALER_DENOMINATION_CS:
+                                      bs->details.blinded_rsa_signature));
+    return ps;
+  case GNUNET_CRYPTO_BSA_CS:
     ps.object = GNUNET_JSON_PACK (
       GNUNET_JSON_pack_string ("cipher",
                                "CS"),
       GNUNET_JSON_pack_uint64 ("b",
-                               sig->details.blinded_cs_answer.b),
+                               bs->details.blinded_cs_answer.b),
       GNUNET_JSON_pack_data_auto ("s",
-                                  &sig->details.blinded_cs_answer.s_scalar));
-    break;
-  default:
-    GNUNET_assert (0);
+                                  &bs->details.blinded_cs_answer.s_scalar));
+    return ps;
   }
+  GNUNET_assert (0);
   return ps;
 }
 
@@ -252,40 +265,43 @@ TALER_JSON_pack_blinded_planchet (
   const char *name,
   const struct TALER_BlindedPlanchet *blinded_planchet)
 {
+  const struct GNUNET_CRYPTO_BlindedMessage *bm;
   struct GNUNET_JSON_PackSpec ps = {
     .field_name = name,
   };
 
   if (NULL == blinded_planchet)
     return ps;
-  switch (blinded_planchet->cipher)
+  bm = blinded_planchet->blinded_message;
+  switch (bm->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     ps.object = GNUNET_JSON_PACK (
       GNUNET_JSON_pack_string ("cipher",
                                "RSA"),
       GNUNET_JSON_pack_data_varsize (
         "rsa_blinded_planchet",
-        blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
-        blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size));
-    break;
-  case TALER_DENOMINATION_CS:
+        bm->details.rsa_blinded_message.blinded_msg,
+        bm->details.rsa_blinded_message.blinded_msg_size));
+    return ps;
+  case GNUNET_CRYPTO_BSA_CS:
     ps.object = GNUNET_JSON_PACK (
       GNUNET_JSON_pack_string ("cipher",
                                "CS"),
       GNUNET_JSON_pack_data_auto (
         "cs_nonce",
-        &blinded_planchet->details.cs_blinded_planchet.nonce),
+        &bm->details.cs_blinded_message.nonce),
       GNUNET_JSON_pack_data_auto (
         "cs_blinded_c0",
-        &blinded_planchet->details.cs_blinded_planchet.c[0]),
+        &bm->details.cs_blinded_message.c[0]),
       GNUNET_JSON_pack_data_auto (
         "cs_blinded_c1",
-        &blinded_planchet->details.cs_blinded_planchet.c[1]));
-    break;
-  default:
-    GNUNET_assert (0);
+        &bm->details.cs_blinded_message.c[1]));
+    return ps;
   }
+  GNUNET_assert (0);
   return ps;
 }
 
diff --git a/src/lib/exchange_api_age_withdraw.c 
b/src/lib/exchange_api_age_withdraw.c
index ea9c0371..6c6460b2 100644
--- a/src/lib/exchange_api_age_withdraw.c
+++ b/src/lib/exchange_api_age_withdraw.c
@@ -67,25 +67,40 @@ struct CoinCandidate
  */
 struct CSRClosure
 {
-  /* Points to the actual candidate in CoinData.coin_candidates, to continue
-   * to build its contents based on the results from /csr-withdraw */
+  /**
+   * Points to the actual candidate in CoinData.coin_candidates, to continue
+   * to build its contents based on the results from /csr-withdraw
+   */
   struct CoinCandidate *candidate;
 
-  /* The planchet to finally generate.  Points to the corresponding candidate
-   * in CoindData.planchet_details */
+  /**
+   * The planchet to finally generate.  Points to the corresponding candidate
+   * in CoindData.planchet_details
+   */
   struct TALER_PlanchetDetail *planchet;
 
-  /* Handler to the originating call to /age-withdraw, needed to either
+  /**
+   * Handler to the originating call to /age-withdraw, needed to either
    * cancel the running age-withdraw request (on failure of the current call
    * to /csr-withdraw), or to eventually perform the protocol, once all
-   * csr-withdraw requests have successfully finished. */
+   * csr-withdraw requests have successfully finished.
+   */
   struct TALER_EXCHANGE_AgeWithdrawHandle *age_withdraw_handle;
 
-  /* Denomination information, needed for CS coins for the
-   * step after /csr-withdraw */
+  /**
+   * Session nonce.
+   */
+  union GNUNET_CRYPTO_BlindSessionNonce nonce;
+
+  /**
+   * Denomination information, needed for CS coins for the
+   * step after /csr-withdraw
+   */
   const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
 
-  /* Handler for the CS R request */
+  /**
+   * Handler for the CS R request
+   */
   struct TALER_EXCHANGE_CsRWithdrawHandle *csr_withdraw_handle;
 };
 
@@ -663,13 +678,19 @@ copy_results (
   struct TALER_EXCHANGE_AgeWithdrawResponse resp = {
     .hr = awbr->hr,
     .details = {
-      .ok = { .noreveal_index = awbr->details.ok.noreveal_index,
-              .h_commitment = awbr->details.ok.h_commitment,
-              .exchange_pub = awbr->details.ok.exchange_pub,
-              .num_coins = awh->num_coins,
-              .coin_details = details,
-              .blinded_coin_hs = blinded_coin_hs},
-    },
+      .ok = {
+        .noreveal_index = awbr->details.ok.noreveal_index,
+        .h_commitment = awbr->details.ok.h_commitment,
+        .exchange_pub = awbr->details.ok.exchange_pub,
+        .num_coins = awh->num_coins,
+        .coin_details = details,
+        .blinded_coin_hs = blinded_coin_hs
+      }
+
+
+    }
+
+
   };
 
   for (size_t n = 0; n< awh->num_coins; n++)
@@ -678,10 +699,8 @@ copy_results (
     details[n].planchet = awh->coin_data[n].planchet_details[k];
     blinded_coin_hs[n] = awh->coin_data[n].coin_candidates[k].blinded_coin_h;
   }
-
   awh->callback (awh->callback_cls,
                  &resp);
-
   awh->callback = NULL;
 }
 
@@ -795,8 +814,8 @@ csr_withdraw_done (
       bool success = false;
       /* Complete the initialization of the coin with CS denomination */
       can->details.alg_values = csrr->details.ok.alg_values;
-      GNUNET_assert (can->details.alg_values.cipher
-                     == TALER_DENOMINATION_CS);
+      GNUNET_assert (can->details.alg_values.blinding_inputs->cipher
+                     == GNUNET_CRYPTO_BSA_CS);
       TALER_planchet_setup_coin_priv (&can->secret,
                                       &can->details.alg_values,
                                       &can->details.coin_priv);
@@ -810,6 +829,7 @@ csr_withdraw_done (
             TALER_planchet_prepare (&csr->denom_pub->key,
                                     &can->details.alg_values,
                                     &can->details.blinding_key,
+                                    &csr->nonce,
                                     &can->details.coin_priv,
                                     &can->details.h_age_commitment,
                                     &can->details.h_coin_pub,
@@ -912,11 +932,10 @@ prepare_coins (
       TALER_age_commitment_hash (&can->details.age_commitment_proof.commitment,
                                  &can->details.h_age_commitment);
 
-      switch (input->denom_pub->key.cipher)
+      switch (input->denom_pub->key.bsign_pub_key->cipher)
       {
-      case TALER_DENOMINATION_RSA:
+      case GNUNET_CRYPTO_BSA_RSA:
         {
-          can->details.alg_values.cipher = TALER_DENOMINATION_RSA;
           TALER_planchet_setup_coin_priv (&can->secret,
                                           &can->details.alg_values,
                                           &can->details.coin_priv);
@@ -925,8 +944,9 @@ prepare_coins (
                                                  &can->details.blinding_key);
           FAIL_IF (GNUNET_OK !=
                    TALER_planchet_prepare (&cd->denom_pub.key,
-                                           &can->details.alg_values,
+                                           NULL,
                                            &can->details.blinding_key,
+                                           NULL,
                                            &can->details.coin_priv,
                                            &can->details.h_age_commitment,
                                            &can->details.h_coin_pub,
@@ -937,10 +957,8 @@ prepare_coins (
                                        &can->blinded_coin_h));
           break;
         }
-      case TALER_DENOMINATION_CS:
+      case GNUNET_CRYPTO_BSA_CS:
         {
-          can->details.alg_values.cipher = TALER_DENOMINATION_CS;
-
           struct CSRClosure *cls = &cd->csr_cls[k];
           /**
            * Save the handler and the denomination for the callback
@@ -949,21 +967,15 @@ prepare_coins (
           cls->candidate = can;
           cls->planchet = planchet;
           cls->denom_pub = &cd->denom_pub;
-
           TALER_cs_withdraw_nonce_derive (
             &can->secret,
-            &planchet->blinded_planchet.details.cs_blinded_planchet.nonce);
-
-          /* Note that we only initialize the first half
-             of the blinded_planchet here; the other part
-             will be done after the /csr-withdraw request! */
-          planchet->blinded_planchet.cipher = TALER_DENOMINATION_CS;
+            &cls->nonce.cs_nonce);
           cls->csr_withdraw_handle =
             TALER_EXCHANGE_csr_withdraw (
               awh->curl_ctx,
               awh->exchange_url,
               &cd->denom_pub,
-              &planchet->blinded_planchet.details.cs_blinded_planchet.nonce,
+              &cls->nonce.cs_nonce,
               &csr_withdraw_done,
               cls);
           FAIL_IF (NULL == cls->csr_withdraw_handle);
diff --git a/src/lib/exchange_api_batch_withdraw.c 
b/src/lib/exchange_api_batch_withdraw.c
index a1fcccce..d17a00f1 100644
--- a/src/lib/exchange_api_batch_withdraw.c
+++ b/src/lib/exchange_api_batch_withdraw.c
@@ -54,9 +54,14 @@ struct CoinData
   const struct TALER_AgeCommitmentHash *ach;
 
   /**
-   *  blinding secret
+   * blinding secret
    */
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
+
+  /**
+   * Session nonce.
+   */
+  union GNUNET_CRYPTO_BlindSessionNonce nonce;
 
   /**
    * Private key of the coin we are withdrawing.
@@ -79,7 +84,7 @@ struct CoinData
   struct TALER_CoinPubHashP c_hash;
 
   /**
-   * Handler for the CS R request (only used for TALER_DENOMINATION_CS 
denominations)
+   * Handler for the CS R request (only used for GNUNET_CRYPTO_BSA_CS 
denominations)
    */
   struct TALER_EXCHANGE_CsRWithdrawHandle *csrh;
 
@@ -295,7 +300,8 @@ withdraw_cs_stage_two_callback (
   };
 
   cd->csrh = NULL;
-  GNUNET_assert (TALER_DENOMINATION_CS == cd->pk.key.cipher);
+  GNUNET_assert (GNUNET_CRYPTO_BSA_CS ==
+                 cd->pk.key.bsign_pub_key->cipher);
   switch (csrr->hr.http_status)
   {
   case MHD_HTTP_OK:
@@ -306,12 +312,11 @@ withdraw_cs_stage_two_callback (
     TALER_planchet_blinding_secret_create (&cd->ps,
                                            &cd->alg_values,
                                            &cd->bks);
-    /* This initializes the 2nd half of the
-       wh->pd.blinded_planchet! */
     if (GNUNET_OK !=
         TALER_planchet_prepare (&cd->pk.key,
                                 &cd->alg_values,
                                 &cd->bks,
+                                &cd->nonce,
                                 &cd->priv,
                                 cd->ach,
                                 &cd->c_hash,
@@ -367,11 +372,10 @@ TALER_EXCHANGE_batch_withdraw (
     cd->pk = *wci->pk;
     TALER_denom_pub_deep_copy (&cd->pk.key,
                                &wci->pk->key);
-    switch (wci->pk->key.cipher)
+    switch (wci->pk->key.bsign_pub_key->cipher)
     {
-    case TALER_DENOMINATION_RSA:
+    case GNUNET_CRYPTO_BSA_RSA:
       {
-        cd->alg_values.cipher = TALER_DENOMINATION_RSA;
         TALER_planchet_setup_coin_priv (&cd->ps,
                                         &cd->alg_values,
                                         &cd->priv);
@@ -380,8 +384,9 @@ TALER_EXCHANGE_batch_withdraw (
                                                &cd->bks);
         if (GNUNET_OK !=
             TALER_planchet_prepare (&cd->pk.key,
-                                    &cd->alg_values,
+                                    NULL,
                                     &cd->bks,
+                                    NULL,
                                     &cd->priv,
                                     cd->ach,
                                     &cd->c_hash,
@@ -393,20 +398,16 @@ TALER_EXCHANGE_batch_withdraw (
         }
         break;
       }
-    case TALER_DENOMINATION_CS:
+    case GNUNET_CRYPTO_BSA_CS:
       {
         TALER_cs_withdraw_nonce_derive (
           &cd->ps,
-          &cd->pd.blinded_planchet.details.cs_blinded_planchet.nonce);
-        /* Note that we only initialize the first half
-           of the blinded_planchet here; the other part
-           will be done after the /csr-withdraw request! */
-        cd->pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
+          &cd->nonce.cs_nonce);
         cd->csrh = TALER_EXCHANGE_csr_withdraw (
           curl_ctx,
           exchange_url,
           &cd->pk,
-          &cd->pd.blinded_planchet.details.cs_blinded_planchet.nonce,
+          &cd->nonce.cs_nonce,
           &withdraw_cs_stage_two_callback,
           cd);
         if (NULL == cd->csrh)
diff --git a/src/lib/exchange_api_csr_melt.c b/src/lib/exchange_api_csr_melt.c
index f59995af..f5887bd6 100644
--- a/src/lib/exchange_api_csr_melt.c
+++ b/src/lib/exchange_api_csr_melt.c
@@ -234,7 +234,8 @@ TALER_EXCHANGE_csr_melt (
     return NULL;
   }
   for (unsigned int i = 0; i<nks_len; i++)
-    if (TALER_DENOMINATION_CS != nks[i].pk->key.cipher)
+    if (GNUNET_CRYPTO_BSA_CS !=
+        nks[i].pk->key.bsign_pub_key->cipher)
     {
       GNUNET_break (0);
       return NULL;
diff --git a/src/lib/exchange_api_csr_withdraw.c 
b/src/lib/exchange_api_csr_withdraw.c
index 4c1d83a9..fa2b0dc8 100644
--- a/src/lib/exchange_api_csr_withdraw.c
+++ b/src/lib/exchange_api_csr_withdraw.c
@@ -203,13 +203,14 @@ TALER_EXCHANGE_csr_withdraw (
   struct GNUNET_CURL_Context *curl_ctx,
   const char *exchange_url,
   const struct TALER_EXCHANGE_DenomPublicKey *pk,
-  const struct TALER_CsNonce *nonce,
+  const struct GNUNET_CRYPTO_CsSessionNonce *nonce,
   TALER_EXCHANGE_CsRWithdrawCallback res_cb,
   void *res_cb_cls)
 {
   struct TALER_EXCHANGE_CsRWithdrawHandle *csrh;
 
-  if (TALER_DENOMINATION_CS != pk->key.cipher)
+  if (GNUNET_CRYPTO_BSA_CS !=
+      pk->key.bsign_pub_key->cipher)
   {
     GNUNET_break (0);
     return NULL;
@@ -233,10 +234,10 @@ TALER_EXCHANGE_csr_withdraw (
     req = GNUNET_JSON_PACK (
       GNUNET_JSON_pack_data_varsize ("nonce",
                                      nonce,
-                                     sizeof(struct TALER_CsNonce)),
+                                     sizeof(*nonce)),
       GNUNET_JSON_pack_data_varsize ("denom_pub_hash",
                                      &pk->h_key,
-                                     sizeof(struct TALER_DenominationHashP)));
+                                     sizeof(pk->h_key)));
     GNUNET_assert (NULL != req);
     eh = TALER_EXCHANGE_curl_easy_get_ (csrh->url);
     if ( (NULL == eh) ||
diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index 50a1a9ce..24d1590c 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -458,7 +458,7 @@ parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey 
*sign_key,
 static enum GNUNET_GenericReturnValue
 parse_json_denomkey_partially (
   struct TALER_EXCHANGE_DenomPublicKey *denom_key,
-  enum TALER_DenominationCipher cipher,
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher,
   bool check_sigs,
   const json_t *denom_key_obj,
   struct TALER_MasterPublicKeyP *master_key,
@@ -1111,7 +1111,6 @@ decode_keys_json (const json_t *resp_obj,
            denomination.  Required to make the validity check inside
            parse_json_denomkey_partially pass */
         struct TALER_EXCHANGE_DenomPublicKey dk = {
-          .key.cipher = group.cipher,
           .value = group.value,
           .fees = group.fees,
           .key.age_mask = group.age_mask
@@ -1978,10 +1977,10 @@ add_grp (void *cls,
   (void) key;
   switch (gd->meta.cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     cipher = age_restricted ? "RSA+age_restricted" : "RSA";
     break;
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     cipher = age_restricted ? "CS+age_restricted" : "CS";
     break;
   default:
@@ -2125,7 +2124,6 @@ TALER_EXCHANGE_keys_to_json (const struct 
TALER_EXCHANGE_Keys *kd)
     {
       const struct TALER_EXCHANGE_DenomPublicKey *dk = &kd->denom_keys[i];
       struct TALER_DenominationGroup meta = {
-        .cipher = dk->key.cipher,
         .value = dk->value,
         .fees = dk->fees,
         .age_mask = dk->key.age_mask
@@ -2159,18 +2157,18 @@ TALER_EXCHANGE_keys_to_json (const struct 
TALER_EXCHANGE_Keys *kd)
       }
       switch (meta.cipher)
       {
-      case TALER_DENOMINATION_RSA:
+      case GNUNET_CRYPTO_BSA_RSA:
         key_spec =
           GNUNET_JSON_pack_rsa_public_key (
             "rsa_pub",
-            dk->key.details.rsa_public_key);
+            dk->key.bsign_pub_key->details.rsa_public_key);
         break;
-      case TALER_DENOMINATION_CS:
+      case GNUNET_CRYPTO_BSA_CS:
         key_spec =
           GNUNET_JSON_pack_data_varsize (
             "cs_pub",
-            &dk->key.details.cs_public_key,
-            sizeof (dk->key.details.cs_public_key));
+            &dk->key.bsign_pub_key->details.cs_public_key,
+            sizeof (dk->key.bsign_pub_key->details.cs_public_key));
         break;
       default:
         GNUNET_assert (false);
diff --git a/src/lib/exchange_api_link.c b/src/lib/exchange_api_link.c
index f408b87d..2d56ec91 100644
--- a/src/lib/exchange_api_link.c
+++ b/src/lib/exchange_api_link.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2015-2021 Taler Systems SA
+  Copyright (C) 2015-2023 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -89,9 +89,9 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
   struct TALER_BlindedDenominationSignature bsig;
   struct TALER_DenominationPublicKey rpub;
   struct TALER_CoinSpendSignatureP link_sig;
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
   struct TALER_ExchangeWithdrawValues alg_values;
-  struct TALER_CsNonce nonce;
+  union GNUNET_CRYPTO_BlindSessionNonce nonce;
   bool no_nonce;
   uint32_t coin_idx;
   struct GNUNET_JSON_Specification spec[] = {
@@ -163,6 +163,9 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
         &rpub,
         &alg_values,
         &bks,
+        no_nonce
+        ? NULL
+        : &nonce,
         &lci->coin_priv,
         pah,
         &c_hash,
@@ -172,16 +175,6 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle 
*lh,
     GNUNET_JSON_parse_free (spec);
     return GNUNET_SYSERR;
   }
-  if (TALER_DENOMINATION_CS == alg_values.cipher)
-  {
-    if (no_nonce)
-    {
-      GNUNET_break_op (0);
-      GNUNET_JSON_parse_free (spec);
-      return GNUNET_SYSERR;
-    }
-    pd.blinded_planchet.details.cs_blinded_planchet.nonce = nonce;
-  }
   /* extract coin and signature */
   if (GNUNET_OK !=
       TALER_denom_sig_unblind (&lci->sig,
diff --git a/src/lib/exchange_api_management_get_keys.c 
b/src/lib/exchange_api_management_get_keys.c
index 03339c66..b88ddc20 100644
--- a/src/lib/exchange_api_management_get_keys.c
+++ b/src/lib/exchange_api_management_get_keys.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2015-2020 Taler Systems SA
+  Copyright (C) 2015-2023 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -228,14 +228,15 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle 
*gh,
 
       TALER_denom_pub_hash (&denom_key->key,
                             &h_denom_pub);
-      switch (denom_key->key.cipher)
+      switch (denom_key->key.bsign_pub_key->cipher)
       {
-      case TALER_DENOMINATION_RSA:
+      case GNUNET_CRYPTO_BSA_RSA:
         {
           struct TALER_RsaPubHashP h_rsa;
 
-          TALER_rsa_pub_hash (denom_key->key.details.rsa_public_key,
-                              &h_rsa);
+          TALER_rsa_pub_hash (
+            denom_key->key.bsign_pub_key->details.rsa_public_key,
+            &h_rsa);
           if (GNUNET_OK !=
               TALER_exchange_secmod_rsa_verify (&h_rsa,
                                                 section_name,
@@ -250,12 +251,13 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle 
*gh,
           }
         }
         break;
-      case TALER_DENOMINATION_CS:
+      case GNUNET_CRYPTO_BSA_CS:
         {
           struct TALER_CsPubHashP h_cs;
 
-          TALER_cs_pub_hash (&denom_key->key.details.cs_public_key,
-                             &h_cs);
+          TALER_cs_pub_hash (
+            &denom_key->key.bsign_pub_key->details.cs_public_key,
+            &h_cs);
           if (GNUNET_OK !=
               TALER_exchange_secmod_cs_verify (&h_cs,
                                                section_name,
diff --git a/src/lib/exchange_api_melt.c b/src/lib/exchange_api_melt.c
index ba4241da..90677276 100644
--- a/src/lib/exchange_api_melt.c
+++ b/src/lib/exchange_api_melt.c
@@ -460,18 +460,16 @@ csr_cb (void *cls,
       &mh->rd->fresh_pks[i];
     struct TALER_ExchangeWithdrawValues *wv = &mh->mbds[i].alg_value;
 
-    switch (fresh_pk->key.cipher)
+    switch (fresh_pk->key.bsign_pub_key->cipher)
     {
-    case TALER_DENOMINATION_INVALID:
+    case GNUNET_CRYPTO_BSA_INVALID:
       GNUNET_break (0);
       fail_mh (mh,
                TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR);
       return;
-    case TALER_DENOMINATION_RSA:
-      GNUNET_assert (TALER_DENOMINATION_RSA == wv->cipher);
+    case GNUNET_CRYPTO_BSA_RSA:
       break;
-    case TALER_DENOMINATION_CS:
-      GNUNET_assert (TALER_DENOMINATION_CS == wv->cipher);
+    case GNUNET_CRYPTO_BSA_CS:
       *wv = csrr->details.ok.alg_values[nks_off];
       nks_off++;
       break;
@@ -521,20 +519,17 @@ TALER_EXCHANGE_melt (
   for (unsigned int i = 0; i<rd->fresh_pks_len; i++)
   {
     const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk = &rd->fresh_pks[i];
-    struct TALER_ExchangeWithdrawValues *wv = &mh->mbds[i].alg_value;
 
-    switch (fresh_pk->key.cipher)
+    switch (fresh_pk->key.bsign_pub_key->cipher)
     {
-    case TALER_DENOMINATION_INVALID:
+    case GNUNET_CRYPTO_BSA_INVALID:
       GNUNET_break (0);
       GNUNET_free (mh->mbds);
       GNUNET_free (mh);
       return NULL;
-    case TALER_DENOMINATION_RSA:
-      wv->cipher = TALER_DENOMINATION_RSA;
+    case GNUNET_CRYPTO_BSA_RSA:
       break;
-    case TALER_DENOMINATION_CS:
-      wv->cipher = TALER_DENOMINATION_CS;
+    case GNUNET_CRYPTO_BSA_CS:
       nks[nks_off].pk = fresh_pk;
       nks[nks_off].cnc_num = nks_off;
       nks_off++;
diff --git a/src/lib/exchange_api_recoup.c b/src/lib/exchange_api_recoup.c
index cfd265f0..56499f38 100644
--- a/src/lib/exchange_api_recoup.c
+++ b/src/lib/exchange_api_recoup.c
@@ -245,7 +245,7 @@ TALER_EXCHANGE_recoup (
   CURL *eh;
   char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32];
   struct TALER_CoinSpendPrivateKeyP coin_priv;
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
 
   ph = GNUNET_new (struct TALER_EXCHANGE_RecoupHandle);
   TALER_planchet_setup_coin_priv (ps,
@@ -273,22 +273,32 @@ TALER_EXCHANGE_recoup (
                                 &ph->coin_sig),
     GNUNET_JSON_pack_data_auto ("coin_blind_key_secret",
                                 &bks));
-  if (TALER_DENOMINATION_CS == denom_sig->cipher)
+  switch (denom_sig->unblinded_sig->cipher)
   {
-    struct TALER_CsNonce nonce;
-
-    /* NOTE: this is not elegant, and as per the note in TALER_coin_ev_hash()
-       it is not strictly clear that the nonce is needed. Best case would be
-       to find a way to include it more 'naturally' somehow, for example with
-       the variant union version of bks! */
-    TALER_cs_withdraw_nonce_derive (ps,
-                                    &nonce);
-    GNUNET_assert (
-      0 ==
-      json_object_set_new (recoup_obj,
-                           "cs_nonce",
-                           GNUNET_JSON_from_data_auto (
-                             &nonce)));
+  case GNUNET_CRYPTO_BSA_INVALID:
+    json_decref (recoup_obj);
+    GNUNET_break (0);
+    GNUNET_free (ph);
+    return NULL;
+  case GNUNET_CRYPTO_BSA_RSA:
+    break;
+  case GNUNET_CRYPTO_BSA_CS:
+    {
+      union GNUNET_CRYPTO_BlindSessionNonce nonce;
+
+      /* NOTE: this is not elegant, and as per the note in TALER_coin_ev_hash()
+         it is not strictly clear that the nonce is needed. Best case would be
+         to find a way to include it more 'naturally' somehow, for example with
+         the variant union version of bks! */
+      TALER_cs_withdraw_nonce_derive (ps,
+                                      &nonce.cs_nonce);
+      GNUNET_assert (
+        0 ==
+        json_object_set_new (recoup_obj,
+                             "cs_nonce",
+                             GNUNET_JSON_from_data_auto (
+                               &nonce)));
+    }
   }
 
   {
diff --git a/src/lib/exchange_api_recoup_refresh.c 
b/src/lib/exchange_api_recoup_refresh.c
index 0bcd44de..0c2e21cb 100644
--- a/src/lib/exchange_api_recoup_refresh.c
+++ b/src/lib/exchange_api_recoup_refresh.c
@@ -235,7 +235,7 @@ TALER_EXCHANGE_recoup_refresh (
   CURL *eh;
   char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32];
   struct TALER_CoinSpendPrivateKeyP coin_priv;
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
 
   GNUNET_assert (NULL != recoup_cb);
   ph = GNUNET_new (struct TALER_EXCHANGE_RecoupRefreshHandle);
@@ -271,23 +271,34 @@ TALER_EXCHANGE_recoup_refresh (
     GNUNET_JSON_pack_data_auto ("coin_blind_key_secret",
                                 &bks));
 
-  if (TALER_DENOMINATION_CS == denom_sig->cipher)
+  switch (denom_sig->unblinded_sig->cipher)
   {
-    struct TALER_CsNonce nonce;
-
-    /* NOTE: this is not elegant, and as per the note in TALER_coin_ev_hash()
-       it is not strictly clear that the nonce is needed. Best case would be
-       to find a way to include it more 'naturally' somehow, for example with
-       the variant union version of bks! */
-    TALER_cs_refresh_nonce_derive (rms,
-                                   idx,
-                                   &nonce);
-    GNUNET_assert (
-      0 ==
-      json_object_set_new (recoup_obj,
-                           "cs_nonce",
-                           GNUNET_JSON_from_data_auto (
-                             &nonce)));
+  case GNUNET_CRYPTO_BSA_INVALID:
+    json_decref (recoup_obj);
+    GNUNET_break (0);
+    GNUNET_free (ph);
+    return NULL;
+  case GNUNET_CRYPTO_BSA_RSA:
+    break;
+  case GNUNET_CRYPTO_BSA_CS:
+    {
+      union GNUNET_CRYPTO_BlindSessionNonce nonce;
+
+      /* NOTE: this is not elegant, and as per the note in TALER_coin_ev_hash()
+         it is not strictly clear that the nonce is needed. Best case would be
+         to find a way to include it more 'naturally' somehow, for example with
+         the variant union version of bks! */
+      TALER_cs_refresh_nonce_derive (rms,
+                                     idx,
+                                     &nonce.cs_nonce);
+      GNUNET_assert (
+        0 ==
+        json_object_set_new (recoup_obj,
+                             "cs_nonce",
+                             GNUNET_JSON_from_data_auto (
+                               &nonce)));
+    }
+    break;
   }
 
   {
diff --git a/src/lib/exchange_api_refresh_common.c 
b/src/lib/exchange_api_refresh_common.c
index 0a6665b5..57011a6b 100644
--- a/src/lib/exchange_api_refresh_common.c
+++ b/src/lib/exchange_api_refresh_common.c
@@ -68,7 +68,7 @@ TALER_EXCHANGE_get_melt_data_ (
 {
   struct TALER_Amount total;
   struct TALER_CoinSpendPublicKeyP coin_pub;
-  struct TALER_CsNonce nonces[rd->fresh_pks_len];
+  union GNUNET_CRYPTO_BlindSessionNonce nonces[rd->fresh_pks_len];
   bool uses_cs = false;
 
   GNUNET_CRYPTO_eddsa_key_get_public (&rd->melt_priv.eddsa_priv,
@@ -99,19 +99,27 @@ TALER_EXCHANGE_get_melt_data_ (
   {
     struct FreshCoinData *fcd = &md->fcds[j];
 
-    if (alg_values[j].cipher != rd->fresh_pks[j].key.cipher)
+    switch (fcd->fresh_pk.bsign_pub_key->cipher)
     {
+    case GNUNET_CRYPTO_BSA_INVALID:
       GNUNET_break (0);
       TALER_EXCHANGE_free_melt_data_ (md);
       return GNUNET_SYSERR;
-    }
-    if (TALER_DENOMINATION_CS == alg_values[j].cipher)
-    {
+    case GNUNET_CRYPTO_BSA_RSA:
+      break;
+    case GNUNET_CRYPTO_BSA_CS:
+      if (alg_values[j].blinding_inputs->cipher !=
+          fcd->fresh_pk.bsign_pub_key->cipher)
+      {
+        GNUNET_break (0);
+        TALER_EXCHANGE_free_melt_data_ (md);
+        return GNUNET_SYSERR;
+      }
       uses_cs = true;
-      TALER_cs_refresh_nonce_derive (
-        rms,
-        j,
-        &nonces[j]);
+      TALER_cs_refresh_nonce_derive (rms,
+                                     j,
+                                     &nonces[j].cs_nonce);
+      break;
     }
     TALER_denom_pub_deep_copy (&fcd->fresh_pk,
                                &rd->fresh_pks[j].key);
@@ -170,7 +178,7 @@ TALER_EXCHANGE_get_melt_data_ (
       struct TALER_CoinSpendPrivateKeyP *coin_priv = &fcd->coin_priv;
       struct TALER_PlanchetMasterSecretP *ps = &fcd->ps[i];
       struct TALER_RefreshCoinData *rcd = &md->rcd[i][j];
-      union TALER_DenominationBlindingKeyP *bks = &fcd->bks[i];
+      union GNUNET_CRYPTO_BlindingSecretP *bks = &fcd->bks[i];
       struct TALER_PlanchetDetail pd;
       struct TALER_CoinPubHashP c_hash;
       struct TALER_AgeCommitmentHash ach;
@@ -205,13 +213,11 @@ TALER_EXCHANGE_get_melt_data_ (
         pah = &ach;
       }
 
-      if (TALER_DENOMINATION_CS == alg_values[j].cipher)
-        pd.blinded_planchet.details.cs_blinded_planchet.nonce = nonces[j];
-
       if (GNUNET_OK !=
           TALER_planchet_prepare (&fcd->fresh_pk,
                                   &alg_values[j],
                                   bks,
+                                  &nonces[j],
                                   coin_priv,
                                   pah,
                                   &c_hash,
diff --git a/src/lib/exchange_api_refresh_common.h 
b/src/lib/exchange_api_refresh_common.h
index 0cb80f17..f596e1e9 100644
--- a/src/lib/exchange_api_refresh_common.h
+++ b/src/lib/exchange_api_refresh_common.h
@@ -109,7 +109,7 @@ struct FreshCoinData
    * Blinding key secrets for the coins, depending on the
    * cut-and-choose.
    */
-  union TALER_DenominationBlindingKeyP bks[TALER_CNC_KAPPA];
+  union GNUNET_CRYPTO_BlindingSecretP bks[TALER_CNC_KAPPA];
 
 };
 
diff --git a/src/lib/exchange_api_refreshes_reveal.c 
b/src/lib/exchange_api_refreshes_reveal.c
index 22068299..a4ea4776 100644
--- a/src/lib/exchange_api_refreshes_reveal.c
+++ b/src/lib/exchange_api_refreshes_reveal.c
@@ -138,7 +138,7 @@ refresh_reveal_ok (struct 
TALER_EXCHANGE_RefreshesRevealHandle *rrh,
       GNUNET_JSON_spec_end ()
     };
     struct TALER_FreshCoin coin;
-    union TALER_DenominationBlindingKeyP bks;
+    union GNUNET_CRYPTO_BlindingSecretP bks;
     const struct TALER_AgeCommitmentHash *pah = NULL;
 
     rci->ps = fcd->ps[rrh->noreveal_index];
@@ -360,7 +360,8 @@ TALER_EXCHANGE_refreshes_reveal (
     const struct TALER_RefreshCoinData *rcd = &md.rcd[noreveal_index][i];
     struct TALER_DenominationHashP denom_hash;
 
-    if (TALER_DENOMINATION_CS == md.fcds[i].fresh_pk.cipher)
+    if (GNUNET_CRYPTO_BSA_CS ==
+        md.fcds[i].fresh_pk.bsign_pub_key->cipher)
       send_rms = true;
     TALER_denom_pub_hash (&md.fcds[i].fresh_pk,
                           &denom_hash);
diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c
index dd6cf673..f6684451 100644
--- a/src/pq/pq_query_helper.c
+++ b/src/pq/pq_query_helper.c
@@ -234,6 +234,7 @@ qconv_denom_pub (void *cls,
                  unsigned int scratch_length)
 {
   const struct TALER_DenominationPublicKey *denom_pub = data;
+  const struct GNUNET_CRYPTO_BlindSignPublicKey *bsp = 
denom_pub->bsign_pub_key;
   size_t tlen;
   size_t len;
   uint32_t be[2];
@@ -245,17 +246,17 @@ qconv_denom_pub (void *cls,
   GNUNET_assert (1 == param_length);
   GNUNET_assert (scratch_length > 0);
   GNUNET_break (NULL == cls);
-  be[0] = htonl ((uint32_t) denom_pub->cipher);
+  be[0] = htonl ((uint32_t) bsp->cipher);
   be[1] = htonl (denom_pub->age_mask.bits);
-  switch (denom_pub->cipher)
+  switch (bsp->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     tlen = GNUNET_CRYPTO_rsa_public_key_encode (
-      denom_pub->details.rsa_public_key,
+      bsp->details.rsa_public_key,
       &tbuf);
     break;
-  case TALER_DENOMINATION_CS:
-    tlen = sizeof (denom_pub->details.cs_public_key);
+  case GNUNET_CRYPTO_BSA_CS:
+    tlen = sizeof (bsp->details.cs_public_key);
     break;
   default:
     GNUNET_assert (0);
@@ -265,17 +266,17 @@ qconv_denom_pub (void *cls,
   GNUNET_memcpy (buf,
                  be,
                  sizeof (be));
-  switch (denom_pub->cipher)
+  switch (bsp->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     GNUNET_memcpy (&buf[sizeof (be)],
                    tbuf,
                    tlen);
     GNUNET_free (tbuf);
     break;
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     GNUNET_memcpy (&buf[sizeof (be)],
-                   &denom_pub->details.cs_public_key,
+                   &bsp->details.cs_public_key,
                    tlen);
     break;
   default:
@@ -330,6 +331,7 @@ qconv_denom_sig (void *cls,
                  unsigned int scratch_length)
 {
   const struct TALER_DenominationSignature *denom_sig = data;
+  const struct GNUNET_CRYPTO_UnblindedSignature *ubs = 
denom_sig->unblinded_sig;
   size_t tlen;
   size_t len;
   uint32_t be[2];
@@ -341,17 +343,17 @@ qconv_denom_sig (void *cls,
   GNUNET_assert (1 == param_length);
   GNUNET_assert (scratch_length > 0);
   GNUNET_break (NULL == cls);
-  be[0] = htonl ((uint32_t) denom_sig->cipher);
+  be[0] = htonl ((uint32_t) ubs->cipher);
   be[1] = htonl (0x00); /* magic marker: unblinded */
-  switch (denom_sig->cipher)
+  switch (ubs->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     tlen = GNUNET_CRYPTO_rsa_signature_encode (
-      denom_sig->details.rsa_signature,
+      ubs->details.rsa_signature,
       &tbuf);
     break;
-  case TALER_DENOMINATION_CS:
-    tlen = sizeof (denom_sig->details.cs_signature);
+  case GNUNET_CRYPTO_BSA_CS:
+    tlen = sizeof (ubs->details.cs_signature);
     break;
   default:
     GNUNET_assert (0);
@@ -361,17 +363,17 @@ qconv_denom_sig (void *cls,
   GNUNET_memcpy (buf,
                  &be,
                  sizeof (be));
-  switch (denom_sig->cipher)
+  switch (ubs->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     GNUNET_memcpy (&buf[sizeof (be)],
                    tbuf,
                    tlen);
     GNUNET_free (tbuf);
     break;
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     GNUNET_memcpy (&buf[sizeof (be)],
-                   &denom_sig->details.cs_signature,
+                   &ubs->details.cs_signature,
                    tlen);
     break;
   default:
@@ -426,6 +428,7 @@ qconv_blinded_denom_sig (void *cls,
                          unsigned int scratch_length)
 {
   const struct TALER_BlindedDenominationSignature *denom_sig = data;
+  const struct GNUNET_CRYPTO_BlindedSignature *bs = denom_sig->blinded_sig;
   size_t tlen;
   size_t len;
   uint32_t be[2];
@@ -437,17 +440,17 @@ qconv_blinded_denom_sig (void *cls,
   GNUNET_assert (1 == param_length);
   GNUNET_assert (scratch_length > 0);
   GNUNET_break (NULL == cls);
-  be[0] = htonl ((uint32_t) denom_sig->cipher);
+  be[0] = htonl ((uint32_t) bs->cipher);
   be[1] = htonl (0x01); /* magic marker: blinded */
-  switch (denom_sig->cipher)
+  switch (bs->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     tlen = GNUNET_CRYPTO_rsa_signature_encode (
-      denom_sig->details.blinded_rsa_signature,
+      bs->details.blinded_rsa_signature,
       &tbuf);
     break;
-  case TALER_DENOMINATION_CS:
-    tlen = sizeof (denom_sig->details.blinded_cs_answer);
+  case GNUNET_CRYPTO_BSA_CS:
+    tlen = sizeof (bs->details.blinded_cs_answer);
     break;
   default:
     GNUNET_assert (0);
@@ -457,17 +460,17 @@ qconv_blinded_denom_sig (void *cls,
   GNUNET_memcpy (buf,
                  &be,
                  sizeof (be));
-  switch (denom_sig->cipher)
+  switch (bs->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     GNUNET_memcpy (&buf[sizeof (be)],
                    tbuf,
                    tlen);
     GNUNET_free (tbuf);
     break;
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     GNUNET_memcpy (&buf[sizeof (be)],
-                   &denom_sig->details.blinded_cs_answer,
+                   &bs->details.blinded_cs_answer,
                    tlen);
     break;
   default:
@@ -522,6 +525,7 @@ qconv_blinded_planchet (void *cls,
                         unsigned int scratch_length)
 {
   const struct TALER_BlindedPlanchet *bp = data;
+  const struct GNUNET_CRYPTO_BlindedMessage *bm = bp->blinded_message;
   size_t tlen;
   size_t len;
   uint32_t be[2];
@@ -532,15 +536,15 @@ qconv_blinded_planchet (void *cls,
   GNUNET_assert (1 == param_length);
   GNUNET_assert (scratch_length > 0);
   GNUNET_break (NULL == cls);
-  be[0] = htonl ((uint32_t) bp->cipher);
+  be[0] = htonl ((uint32_t) bm->cipher);
   be[1] = htonl (0x0100); /* magic marker: blinded */
-  switch (bp->cipher)
+  switch (bm->cipher)
   {
-  case TALER_DENOMINATION_RSA:
-    tlen = bp->details.rsa_blinded_planchet.blinded_msg_size;
+  case GNUNET_CRYPTO_BSA_RSA:
+    tlen = bm->details.rsa_blinded_message.blinded_msg_size;
     break;
-  case TALER_DENOMINATION_CS:
-    tlen = sizeof (bp->details.cs_blinded_planchet);
+  case GNUNET_CRYPTO_BSA_CS:
+    tlen = sizeof (bm->details.cs_blinded_message);
     break;
   default:
     GNUNET_assert (0);
@@ -550,16 +554,16 @@ qconv_blinded_planchet (void *cls,
   GNUNET_memcpy (buf,
                  &be,
                  sizeof (be));
-  switch (bp->cipher)
+  switch (bm->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     GNUNET_memcpy (&buf[sizeof (be)],
-                   bp->details.rsa_blinded_planchet.blinded_msg,
+                   bm->details.rsa_blinded_message.blinded_msg,
                    tlen);
     break;
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     GNUNET_memcpy (&buf[sizeof (be)],
-                   &bp->details.cs_blinded_planchet,
+                   &bm->details.cs_blinded_message,
                    tlen);
     break;
   default:
@@ -613,6 +617,8 @@ qconv_exchange_withdraw_values (void *cls,
                                 unsigned int scratch_length)
 {
   const struct TALER_ExchangeWithdrawValues *alg_values = data;
+  const struct GNUNET_CRYPTO_BlindingInputValues *bi =
+    alg_values->blinding_inputs;
   size_t tlen;
   size_t len;
   uint32_t be[2];
@@ -623,15 +629,15 @@ qconv_exchange_withdraw_values (void *cls,
   GNUNET_assert (1 == param_length);
   GNUNET_assert (scratch_length > 0);
   GNUNET_break (NULL == cls);
-  be[0] = htonl ((uint32_t) alg_values->cipher);
+  be[0] = htonl ((uint32_t) bi->cipher);
   be[1] = htonl (0x010000); /* magic marker: EWV */
-  switch (alg_values->cipher)
+  switch (bi->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     tlen = 0;
     break;
-  case TALER_DENOMINATION_CS:
-    tlen = sizeof (struct TALER_DenominationCSPublicRPairP);
+  case GNUNET_CRYPTO_BSA_CS:
+    tlen = sizeof (struct GNUNET_CRYPTO_CSPublicRPairP);
     break;
   default:
     GNUNET_assert (0);
@@ -641,13 +647,13 @@ qconv_exchange_withdraw_values (void *cls,
   GNUNET_memcpy (buf,
                  &be,
                  sizeof (be));
-  switch (alg_values->cipher)
+  switch (bi->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     break;
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     GNUNET_memcpy (&buf[sizeof (be)],
-                   &alg_values->details.cs_values,
+                   &bi->details.cs_values,
                    tlen);
     break;
   default:
@@ -840,14 +846,14 @@ qconv_array (
   same_sized = (0 != meta->same_size);
 
 #define RETURN_UNLESS(cond) \
-        do { \
-          if (! (cond)) \
-          { \
-            GNUNET_break ((cond)); \
-            noerror = false; \
-            goto DONE; \
-          } \
-        } while (0)
+  do { \
+    if (! (cond)) \
+    { \
+      GNUNET_break ((cond)); \
+      noerror = false; \
+      goto DONE; \
+    } \
+  } while (0)
 
   /* Calculate sizes and check bounds */
   {
@@ -885,16 +891,19 @@ qconv_array (
 
           for (size_t i = 0; i<num; i++)
           {
-            switch (denom_sigs[i].cipher)
+            const struct GNUNET_CRYPTO_BlindedSignature *bs =
+              denom_sigs[i].blinded_sig;
+
+            switch (bs->cipher)
             {
-            case TALER_DENOMINATION_RSA:
+            case GNUNET_CRYPTO_BSA_RSA:
               len = GNUNET_CRYPTO_rsa_signature_encode (
-                denom_sigs[i].details.blinded_rsa_signature,
+                bs->details.blinded_rsa_signature,
                 &buffers[i]);
               RETURN_UNLESS (len != 0);
               break;
-            case TALER_DENOMINATION_CS:
-              len = sizeof (denom_sigs[i].details.blinded_cs_answer);
+            case GNUNET_CRYPTO_BSA_CS:
+              len = sizeof (bs->details.blinded_cs_answer);
               break;
             default:
               GNUNET_assert (0);
@@ -978,9 +987,11 @@ qconv_array (
       case TALER_PQ_array_of_blinded_denom_sig:
         {
           const struct TALER_BlindedDenominationSignature *denom_sigs = data;
+          const struct GNUNET_CRYPTO_BlindedSignature *bs =
+            denom_sigs[i].blinded_sig;
           uint32_t be[2];
 
-          be[0] = htonl ((uint32_t) denom_sigs[i].cipher);
+          be[0] = htonl ((uint32_t) bs->cipher);
           be[1] = htonl (0x01);     /* magic margker: blinded */
           GNUNET_memcpy (out,
                          &be,
@@ -988,18 +999,18 @@ qconv_array (
           out += sizeof(be);
           sz -= sizeof(be);
 
-          switch (denom_sigs[i].cipher)
+          switch (bs->cipher)
           {
-          case TALER_DENOMINATION_RSA:
+          case GNUNET_CRYPTO_BSA_RSA:
             /* For RSA, 'same_sized' must have been false */
             GNUNET_assert (NULL != buffers);
             GNUNET_memcpy (out,
                            buffers[i],
                            sz);
             break;
-          case TALER_DENOMINATION_CS:
+          case GNUNET_CRYPTO_BSA_CS:
             GNUNET_memcpy (out,
-                           &denom_sigs[i].details.blinded_cs_answer,
+                           &bs->details.blinded_cs_answer,
                            sz);
             break;
           default:
diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c
index 95850bcc..06c72267 100644
--- a/src/pq/pq_result_helper.c
+++ b/src/pq/pq_result_helper.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2022 Taler Systems SA
+  Copyright (C) 2014-2023 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -425,6 +425,7 @@ extract_denom_pub (void *cls,
                    void *dst)
 {
   struct TALER_DenominationPublicKey *pk = dst;
+  struct GNUNET_CRYPTO_BlindSignPublicKey *bpk;
   size_t len;
   const char *res;
   int fnum;
@@ -462,33 +463,41 @@ extract_denom_pub (void *cls,
                  sizeof (be));
   res += sizeof (be);
   len -= sizeof (be);
-  pk->cipher = ntohl (be[0]);
+  bpk = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
+  bpk->cipher = ntohl (be[0]);
+  bpk->rc = 1;
   pk->age_mask.bits = ntohl (be[1]);
-  switch (pk->cipher)
+  switch (bpk->cipher)
   {
-  case TALER_DENOMINATION_RSA:
-    pk->details.rsa_public_key
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
+    bpk->details.rsa_public_key
       = GNUNET_CRYPTO_rsa_public_key_decode (res,
                                              len);
-    if (NULL == pk->details.rsa_public_key)
+    if (NULL == bpk->details.rsa_public_key)
     {
       GNUNET_break (0);
+      GNUNET_free (bpk);
       return GNUNET_SYSERR;
     }
+    pk->bsign_pub_key = bpk;
     return GNUNET_OK;
-  case TALER_DENOMINATION_CS:
-    if (sizeof (pk->details.cs_public_key) != len)
+  case GNUNET_CRYPTO_BSA_CS:
+    if (sizeof (bpk->details.cs_public_key) != len)
     {
       GNUNET_break (0);
+      GNUNET_free (bpk);
       return GNUNET_SYSERR;
     }
-    GNUNET_memcpy (&pk->details.cs_public_key,
+    GNUNET_memcpy (&bpk->details.cs_public_key,
                    res,
                    len);
+    pk->bsign_pub_key = bpk;
     return GNUNET_OK;
-  default:
-    GNUNET_break (0);
   }
+  GNUNET_break (0);
+  GNUNET_free (bpk);
   return GNUNET_SYSERR;
 }
 
@@ -548,6 +557,7 @@ extract_denom_sig (void *cls,
                    void *dst)
 {
   struct TALER_DenominationSignature *sig = dst;
+  struct GNUNET_CRYPTO_UnblindedSignature *ubs;
   size_t len;
   const char *res;
   int fnum;
@@ -590,32 +600,40 @@ extract_denom_sig (void *cls,
   }
   res += sizeof (be);
   len -= sizeof (be);
-  sig->cipher = ntohl (be[0]);
-  switch (sig->cipher)
+  ubs = GNUNET_new (struct GNUNET_CRYPTO_UnblindedSignature);
+  ubs->rc = 1;
+  ubs->cipher = ntohl (be[0]);
+  switch (ubs->cipher)
   {
-  case TALER_DENOMINATION_RSA:
-    sig->details.rsa_signature
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
+    ubs->details.rsa_signature
       = GNUNET_CRYPTO_rsa_signature_decode (res,
                                             len);
-    if (NULL == sig->details.rsa_signature)
+    if (NULL == ubs->details.rsa_signature)
     {
       GNUNET_break (0);
+      GNUNET_free (ubs);
       return GNUNET_SYSERR;
     }
+    sig->unblinded_sig = ubs;
     return GNUNET_OK;
-  case TALER_DENOMINATION_CS:
-    if (sizeof (sig->details.cs_signature) != len)
+  case GNUNET_CRYPTO_BSA_CS:
+    if (sizeof (ubs->details.cs_signature) != len)
     {
       GNUNET_break (0);
       return GNUNET_SYSERR;
     }
-    GNUNET_memcpy (&sig->details.cs_signature,
+    GNUNET_memcpy (&ubs->details.cs_signature,
                    res,
                    len);
+    sig->unblinded_sig = ubs;
+    GNUNET_free (ubs);
     return GNUNET_OK;
-  default:
-    GNUNET_break (0);
   }
+  GNUNET_break (0);
+  GNUNET_free (ubs);
   return GNUNET_SYSERR;
 }
 
@@ -675,6 +693,7 @@ extract_blinded_denom_sig (void *cls,
                            void *dst)
 {
   struct TALER_BlindedDenominationSignature *sig = dst;
+  struct GNUNET_CRYPTO_BlindedSignature *bs;
   size_t len;
   const char *res;
   int fnum;
@@ -717,32 +736,40 @@ extract_blinded_denom_sig (void *cls,
   }
   res += sizeof (be);
   len -= sizeof (be);
-  sig->cipher = ntohl (be[0]);
-  switch (sig->cipher)
+  bs = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
+  bs->rc = 1;
+  bs->cipher = ntohl (be[0]);
+  switch (bs->cipher)
   {
-  case TALER_DENOMINATION_RSA:
-    sig->details.blinded_rsa_signature
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
+    bs->details.blinded_rsa_signature
       = GNUNET_CRYPTO_rsa_signature_decode (res,
                                             len);
-    if (NULL == sig->details.blinded_rsa_signature)
+    if (NULL == bs->details.blinded_rsa_signature)
     {
       GNUNET_break (0);
+      GNUNET_free (bs);
       return GNUNET_SYSERR;
     }
+    sig->blinded_sig = bs;
     return GNUNET_OK;
-  case TALER_DENOMINATION_CS:
-    if (sizeof (sig->details.blinded_cs_answer) != len)
+  case GNUNET_CRYPTO_BSA_CS:
+    if (sizeof (bs->details.blinded_cs_answer) != len)
     {
       GNUNET_break (0);
+      GNUNET_free (bs);
       return GNUNET_SYSERR;
     }
-    GNUNET_memcpy (&sig->details.blinded_cs_answer,
+    GNUNET_memcpy (&bs->details.blinded_cs_answer,
                    res,
                    len);
+    sig->blinded_sig = bs;
     return GNUNET_OK;
-  default:
-    GNUNET_break (0);
   }
+  GNUNET_break (0);
+  GNUNET_free (bs);
   return GNUNET_SYSERR;
 }
 
@@ -803,6 +830,7 @@ extract_blinded_planchet (void *cls,
                           void *dst)
 {
   struct TALER_BlindedPlanchet *bp = dst;
+  struct GNUNET_CRYPTO_BlindedMessage *bm;
   size_t len;
   const char *res;
   int fnum;
@@ -845,29 +873,36 @@ extract_blinded_planchet (void *cls,
   }
   res += sizeof (be);
   len -= sizeof (be);
-  bp->cipher = ntohl (be[0]);
-  switch (bp->cipher)
+  bm = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage);
+  bm->rc = 1;
+  bm->cipher = ntohl (be[0]);
+  switch (bm->cipher)
   {
-  case TALER_DENOMINATION_RSA:
-    bp->details.rsa_blinded_planchet.blinded_msg_size
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
+    bm->details.rsa_blinded_message.blinded_msg_size
       = len;
-    bp->details.rsa_blinded_planchet.blinded_msg
+    bm->details.rsa_blinded_message.blinded_msg
       = GNUNET_memdup (res,
                        len);
+    bp->blinded_message = bm;
     return GNUNET_OK;
-  case TALER_DENOMINATION_CS:
-    if (sizeof (bp->details.cs_blinded_planchet) != len)
+  case GNUNET_CRYPTO_BSA_CS:
+    if (sizeof (bm->details.cs_blinded_message) != len)
     {
       GNUNET_break (0);
+      GNUNET_free (bm);
       return GNUNET_SYSERR;
     }
-    GNUNET_memcpy (&bp->details.cs_blinded_planchet,
+    GNUNET_memcpy (&bm->details.cs_blinded_message,
                    res,
                    len);
+    bp->blinded_message = bm;
     return GNUNET_OK;
-  default:
-    GNUNET_break (0);
   }
+  GNUNET_break (0);
+  GNUNET_free (bm);
   return GNUNET_SYSERR;
 }
 
@@ -928,6 +963,7 @@ extract_exchange_withdraw_values (void *cls,
                                   void *dst)
 {
   struct TALER_ExchangeWithdrawValues *alg_values = dst;
+  struct GNUNET_CRYPTO_BlindingInputValues *bi;
   size_t len;
   const char *res;
   int fnum;
@@ -970,29 +1006,37 @@ extract_exchange_withdraw_values (void *cls,
   }
   res += sizeof (be);
   len -= sizeof (be);
-  alg_values->cipher = ntohl (be[0]);
-  switch (alg_values->cipher)
+  bi = GNUNET_new (struct GNUNET_CRYPTO_BlindingInputValues);
+  bi->rc = 1;
+  bi->cipher = ntohl (be[0]);
+  switch (bi->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
     if (0 != len)
     {
       GNUNET_break (0);
+      GNUNET_free (bi);
       return GNUNET_SYSERR;
     }
+    alg_values->blinding_inputs = bi;
     return GNUNET_OK;
-  case TALER_DENOMINATION_CS:
-    if (sizeof (struct TALER_DenominationCSPublicRPairP) != len)
+  case GNUNET_CRYPTO_BSA_CS:
+    if (sizeof (bi->details.cs_values) != len)
     {
       GNUNET_break (0);
+      GNUNET_free (bi);
       return GNUNET_SYSERR;
     }
-    GNUNET_memcpy (&alg_values->details.cs_values,
+    GNUNET_memcpy (&bi->details.cs_values,
                    res,
                    len);
+    alg_values->blinding_inputs = bi;
     return GNUNET_OK;
-  default:
-    GNUNET_break (0);
   }
+  GNUNET_break (0);
+  GNUNET_free (bi);
   return GNUNET_SYSERR;
 }
 
@@ -1076,13 +1120,13 @@ extract_array_generic (
   *((void **) dst) = NULL;
 
   #define FAIL_IF(cond) \
-          do { \
-            if ((cond)) \
-            { \
-              GNUNET_break (! (cond)); \
-              goto FAIL; \
-            } \
-          } while (0)
+  do { \
+    if ((cond)) \
+    { \
+      GNUNET_break (! (cond)); \
+      goto FAIL; \
+    } \
+  } while (0)
 
   col_num = PQfnumber (result, fname);
   FAIL_IF (0 > col_num);
@@ -1223,6 +1267,7 @@ extract_array_generic (
         for (uint32_t i = 0; i < header.dim; i++)
         {
           struct TALER_BlindedDenominationSignature *denom_sig = 
&denom_sigs[i];
+          struct GNUNET_CRYPTO_BlindedSignature *bs;
           uint32_t be[2];
           uint32_t val;
           size_t sz;
@@ -1241,28 +1286,35 @@ extract_array_generic (
 
           in += sizeof(be);
           sz -= sizeof(be);
-
-          denom_sig->cipher = ntohl (be[0]);
-          switch (denom_sig->cipher)
+          bs = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
+          bs->cipher = ntohl (be[0]);
+          switch (bs->cipher)
           {
-          case TALER_DENOMINATION_RSA:
-            denom_sig->details.blinded_rsa_signature =
+          case GNUNET_CRYPTO_BSA_RSA:
+            bs->details.blinded_rsa_signature =
               GNUNET_CRYPTO_rsa_signature_decode (in,
                                                   sz);
-            FAIL_IF (NULL == denom_sig->details.blinded_rsa_signature);
+            if (NULL == bs->details.blinded_rsa_signature)
+            {
+              GNUNET_free (bs);
+              FAIL_IF (true);
+            }
             break;
-
-          case TALER_DENOMINATION_CS:
-            FAIL_IF (sizeof(denom_sig->details.blinded_cs_answer) != sz);
-            GNUNET_memcpy (&denom_sig->details.blinded_cs_answer,
+          case GNUNET_CRYPTO_BSA_CS:
+            if (sizeof(bs->details.blinded_cs_answer) != sz)
+            {
+              GNUNET_free (bs);
+              FAIL_IF (true);
+            }
+            GNUNET_memcpy (&bs->details.blinded_cs_answer,
                            in,
                            sz);
             break;
-
           default:
+            GNUNET_free (bs);
             FAIL_IF (true);
           }
-
+          denom_sig->blinded_sig = bs;
           in += sz;
         }
         return GNUNET_OK;
diff --git a/src/testing/testing_api_cmd_batch_withdraw.c 
b/src/testing/testing_api_cmd_batch_withdraw.c
index f0b9dcad..b455fc06 100644
--- a/src/testing/testing_api_cmd_batch_withdraw.c
+++ b/src/testing/testing_api_cmd_batch_withdraw.c
@@ -59,7 +59,7 @@ struct CoinState
   /**
    * Blinding key used during the operation.
    */
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
 
   /**
    * Values contributed from the exchange during the
diff --git a/src/testing/testing_api_cmd_insert_deposit.c 
b/src/testing/testing_api_cmd_insert_deposit.c
index dd89a48d..03e704c7 100644
--- a/src/testing/testing_api_cmd_insert_deposit.c
+++ b/src/testing/testing_api_cmd_insert_deposit.c
@@ -158,7 +158,7 @@ insert_deposit_run (void *cls,
   GNUNET_assert (GNUNET_OK ==
                  TALER_denom_priv_create (&denom_priv,
                                           &dpk,
-                                          TALER_DENOMINATION_RSA,
+                                          GNUNET_CRYPTO_BSA_RSA,
                                           1024));
   TALER_denom_pub_hash (&dpk,
                         &issue.denom_hash);
@@ -223,19 +223,20 @@ insert_deposit_run (void *cls,
     struct TALER_PlanchetDetail pd;
     struct TALER_BlindedDenominationSignature bds;
     struct TALER_PlanchetMasterSecretP ps;
-    struct TALER_ExchangeWithdrawValues alg_values;
-    union TALER_DenominationBlindingKeyP bks;
+    union GNUNET_CRYPTO_BlindingSecretP bks;
+    const struct TALER_ExchangeWithdrawValues *alg_values;
 
-    alg_values.cipher = TALER_DENOMINATION_RSA;
+    alg_values = TALER_denom_ewv_rsa_singleton ();
     TALER_planchet_blinding_secret_create (&ps,
-                                           &alg_values,
+                                           alg_values,
                                            &bks);
     GNUNET_assert (GNUNET_OK ==
                    TALER_denom_blind (&dpk,
                                       &bks,
                                       NULL, /* no age restriction active */
+                                      NULL, /* no nonce needed */
                                       &deposit.coin.coin_pub,
-                                      &alg_values,
+                                      alg_values,
                                       &c_hash,
                                       &pd.blinded_planchet));
     GNUNET_assert (GNUNET_OK ==
@@ -249,7 +250,7 @@ insert_deposit_run (void *cls,
                                             &bds,
                                             &bks,
                                             &c_hash,
-                                            &alg_values,
+                                            alg_values,
                                             &dpk));
     TALER_blinded_denom_sig_free (&bds);
   }
diff --git a/src/testing/testing_api_cmd_refresh.c 
b/src/testing/testing_api_cmd_refresh.c
index 3b35a73b..ac1a8559 100644
--- a/src/testing/testing_api_cmd_refresh.c
+++ b/src/testing/testing_api_cmd_refresh.c
@@ -80,7 +80,7 @@ struct TALER_TESTING_FreshCoinData
   /**
    * The blinding key (needed for recoup operations).
    */
-  union TALER_DenominationBlindingKeyP blinding_key;
+  union GNUNET_CRYPTO_BlindingSecretP blinding_key;
 
 };
 
diff --git a/src/testing/testing_api_cmd_withdraw.c 
b/src/testing/testing_api_cmd_withdraw.c
index 8a88f60f..b9fde7ef 100644
--- a/src/testing/testing_api_cmd_withdraw.c
+++ b/src/testing/testing_api_cmd_withdraw.c
@@ -113,7 +113,7 @@ struct WithdrawState
   /**
    * Blinding key used during the operation.
    */
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
 
   /**
    * Values contributed from the exchange during the
diff --git a/src/util/crypto.c b/src/util/crypto.c
index caa5a122..8d53f542 100644
--- a/src/util/crypto.c
+++ b/src/util/crypto.c
@@ -214,7 +214,7 @@ TALER_planchet_secret_to_transfer_priv (
 void
 TALER_cs_withdraw_nonce_derive (
   const struct TALER_PlanchetMasterSecretP *ps,
-  struct TALER_CsNonce *nonce)
+  struct GNUNET_CRYPTO_CsSessionNonce *nonce)
 {
   GNUNET_assert (GNUNET_YES ==
                  GNUNET_CRYPTO_kdf (nonce,
@@ -232,7 +232,7 @@ void
 TALER_cs_refresh_nonce_derive (
   const struct TALER_RefreshMasterSecretP *rms,
   uint32_t coin_num_salt,
-  struct TALER_CsNonce *nonce)
+  struct GNUNET_CRYPTO_CsSessionNonce *nonce)
 {
   uint32_t be_salt = htonl (coin_num_salt);
 
@@ -250,10 +250,31 @@ TALER_cs_refresh_nonce_derive (
 }
 
 
+void
+TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa,
+                    struct TALER_RsaPubHashP *h_rsa)
+{
+  GNUNET_CRYPTO_rsa_public_key_hash (rsa,
+                                     &h_rsa->hash);
+
+}
+
+
+void
+TALER_cs_pub_hash (const struct GNUNET_CRYPTO_CsPublicKey *cs,
+                   struct TALER_CsPubHashP *h_cs)
+{
+  GNUNET_CRYPTO_hash (cs,
+                      sizeof(*cs),
+                      &h_cs->hash);
+}
+
+
 enum GNUNET_GenericReturnValue
 TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk,
                         const struct TALER_ExchangeWithdrawValues *alg_values,
-                        const union TALER_DenominationBlindingKeyP *bks,
+                        const union GNUNET_CRYPTO_BlindingSecretP *bks,
+                        const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
                         const struct TALER_CoinSpendPrivateKeyP *coin_priv,
                         const struct TALER_AgeCommitmentHash *ach,
                         struct TALER_CoinPubHashP *c_hash,
@@ -262,12 +283,14 @@ TALER_planchet_prepare (const struct 
TALER_DenominationPublicKey *dk,
 {
   struct TALER_CoinSpendPublicKeyP coin_pub;
 
-  GNUNET_assert (alg_values->cipher == dk->cipher);
+  GNUNET_assert (alg_values->blinding_inputs->cipher ==
+                 dk->bsign_pub_key->cipher);
   GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
                                       &coin_pub.eddsa_pub);
   if (GNUNET_OK !=
       TALER_denom_blind (dk,
                          bks,
+                         nonce,
                          ach,
                          &coin_pub,
                          alg_values,
@@ -294,15 +317,17 @@ enum GNUNET_GenericReturnValue
 TALER_planchet_to_coin (
   const struct TALER_DenominationPublicKey *dk,
   const struct TALER_BlindedDenominationSignature *blind_sig,
-  const union TALER_DenominationBlindingKeyP *bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *bks,
   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   const struct TALER_AgeCommitmentHash *ach,
   const struct TALER_CoinPubHashP *c_hash,
   const struct TALER_ExchangeWithdrawValues *alg_values,
   struct TALER_FreshCoin *coin)
 {
-  if ( (dk->cipher != blind_sig->cipher) ||
-       (dk->cipher != alg_values->cipher) )
+  if ( (dk->bsign_pub_key->cipher !=
+        blind_sig->blinded_sig->cipher) ||
+       (dk->bsign_pub_key->cipher !=
+        alg_values->blinding_inputs->cipher) )
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
diff --git a/src/util/crypto_helper_cs.c b/src/util/crypto_helper_cs.c
index 5f7d3d6f..dae0b6fc 100644
--- a/src/util/crypto_helper_cs.c
+++ b/src/util/crypto_helper_cs.c
@@ -201,13 +201,18 @@ handle_mt_avail (struct TALER_CRYPTO_CsDenominationHelper 
*dh,
   }
 
   {
-    struct TALER_DenominationPublicKey denom_pub;
+    struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
     struct TALER_CsPubHashP h_cs;
 
-    denom_pub.cipher = TALER_DENOMINATION_CS;
-    denom_pub.details.cs_public_key = kan->denom_pub;
+    bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
+    bsign_pub->cipher = GNUNET_CRYPTO_BSA_CS;
+    bsign_pub->rc = 1;
+    bsign_pub->details.cs_public_key = kan->denom_pub;
 
-    TALER_cs_pub_hash (&denom_pub.details.cs_public_key, &h_cs);
+    GNUNET_CRYPTO_hash (&bsign_pub->details.cs_public_key,
+                        sizeof (bsign_pub->details.cs_public_key),
+                        &bsign_pub->pub_key_hash);
+    h_cs.hash = bsign_pub->pub_key_hash;
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Received CS key %s (%s)\n",
                 GNUNET_h2s (&h_cs.hash),
@@ -222,7 +227,7 @@ handle_mt_avail (struct TALER_CRYPTO_CsDenominationHelper 
*dh,
           &kan->secm_sig))
     {
       GNUNET_break_op (0);
-      TALER_denom_pub_free (&denom_pub);
+      GNUNET_CRYPTO_blind_sign_pub_decref (bsign_pub);
       return GNUNET_SYSERR;
     }
     dh->dkc (dh->dkc_cls,
@@ -230,10 +235,10 @@ handle_mt_avail (struct TALER_CRYPTO_CsDenominationHelper 
*dh,
              GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
              GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
              &h_cs,
-             &denom_pub,
+             bsign_pub,
              &kan->secm_pub,
              &kan->secm_sig);
-    TALER_denom_pub_free (&denom_pub);
+    GNUNET_CRYPTO_blind_sign_pub_decref (bsign_pub);
   }
   return GNUNET_OK;
 }
@@ -387,10 +392,10 @@ TALER_CRYPTO_helper_cs_sign (
 {
   enum TALER_ErrorCode ec = TALER_EC_INVALID;
   const struct TALER_CsPubHashP *h_cs = req->h_cs;
-  const struct TALER_BlindedCsPlanchet *blinded_planchet =
-    req->blinded_planchet;
 
-  bs->cipher = TALER_DENOMINATION_INVALID;
+  memset (bs,
+          0,
+          sizeof (*bs));
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Starting signature process\n");
   if (GNUNET_OK !=
@@ -412,7 +417,7 @@ TALER_CRYPTO_helper_cs_sign (
     sr->header.type = htons (TALER_HELPER_CS_MT_REQ_SIGN);
     sr->for_melt = htonl (for_melt ? 1 : 0);
     sr->h_cs = *h_cs;
-    sr->planchet = *blinded_planchet;
+    sr->message = *req->blinded_planchet;
     if (GNUNET_OK !=
         TALER_crypto_helper_send_all (dh->sock,
                                       buf,
@@ -495,13 +500,18 @@ more:
         {
           const struct TALER_CRYPTO_SignResponse *sr =
             (const struct TALER_CRYPTO_SignResponse *) buf;
+          struct GNUNET_CRYPTO_BlindedSignature *blinded_sig;
 
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                       "Received signature\n");
           ec = TALER_EC_NONE;
           finished = true;
-          bs->cipher = TALER_DENOMINATION_CS;
-          bs->details.blinded_cs_answer = sr->cs_answer;
+          blinded_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
+          blinded_sig->cipher = GNUNET_CRYPTO_BSA_CS;
+          blinded_sig->rc = 1;
+          blinded_sig->details.blinded_cs_answer.b = ntohl (sr->b);
+          blinded_sig->details.blinded_cs_answer.s_scalar = sr->cs_answer;
+          bs->blinded_sig = blinded_sig;
           break;
         }
       case TALER_HELPER_CS_MT_RES_SIGN_FAILURE:
@@ -611,11 +621,11 @@ enum TALER_ErrorCode
 TALER_CRYPTO_helper_cs_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh,
                                  const struct TALER_CRYPTO_CsDeriveRequest 
*cdr,
                                  bool for_melt,
-                                 struct TALER_DenominationCSPublicRPairP *crp)
+                                 struct GNUNET_CRYPTO_CSPublicRPairP *crp)
 {
   enum TALER_ErrorCode ec = TALER_EC_INVALID;
   const struct TALER_CsPubHashP *h_cs = cdr->h_cs;
-  const struct TALER_CsNonce *nonce = cdr->nonce;
+  const struct GNUNET_CRYPTO_CsSessionNonce *nonce = cdr->nonce;
 
   memset (crp,
           0,
@@ -795,10 +805,10 @@ more:
 enum TALER_ErrorCode
 TALER_CRYPTO_helper_cs_batch_sign (
   struct TALER_CRYPTO_CsDenominationHelper *dh,
-  const struct TALER_CRYPTO_CsSignRequest *reqs,
   unsigned int reqs_length,
+  const struct TALER_CRYPTO_CsSignRequest reqs[static reqs_length],
   bool for_melt,
-  struct TALER_BlindedDenominationSignature *bss)
+  struct TALER_BlindedDenominationSignature bss[static reqs_length])
 {
   enum TALER_ErrorCode ec = TALER_EC_INVALID;
   unsigned int rpos;
@@ -854,7 +864,7 @@ TALER_CRYPTO_helper_cs_batch_sign (
         csm->header.type = htons (TALER_HELPER_CS_MT_REQ_SIGN);
         csm->for_melt = htonl (for_melt ? 1 : 0);
         csm->h_cs = *csr->h_cs;
-        csm->planchet = *csr->blinded_planchet;
+        csm->message = *csr->blinded_planchet;
         wbuf += sizeof (*csm);
       }
       GNUNET_assert (wbuf == &obuf[mlen]);
@@ -945,12 +955,17 @@ more:
           {
             const struct TALER_CRYPTO_SignResponse *sr =
               (const struct TALER_CRYPTO_SignResponse *) buf;
-
+            struct GNUNET_CRYPTO_BlindedSignature *blinded_sig;
             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                         "Received %u signature\n",
                         wpos);
-            bss[wpos].cipher = TALER_DENOMINATION_CS;
-            bss[wpos].details.blinded_cs_answer = sr->cs_answer;
+            blinded_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
+            blinded_sig->cipher = GNUNET_CRYPTO_BSA_CS;
+            blinded_sig->rc = 1;
+            blinded_sig->details.blinded_cs_answer.b = ntohl (sr->b);
+            blinded_sig->details.blinded_cs_answer.s_scalar = sr->cs_answer;
+
+            bss[wpos].blinded_sig = blinded_sig;
             wpos++;
             if (wpos == rend)
             {
@@ -1040,10 +1055,10 @@ more:
 enum TALER_ErrorCode
 TALER_CRYPTO_helper_cs_r_batch_derive (
   struct TALER_CRYPTO_CsDenominationHelper *dh,
-  const struct TALER_CRYPTO_CsDeriveRequest *cdrs,
   unsigned int cdrs_length,
+  const struct TALER_CRYPTO_CsDeriveRequest cdrs[static cdrs_length],
   bool for_melt,
-  struct TALER_DenominationCSPublicRPairP *crps)
+  struct GNUNET_CRYPTO_CSPublicRPairP crps[static cdrs_length])
 {
   enum TALER_ErrorCode ec = TALER_EC_INVALID;
   unsigned int rpos;
diff --git a/src/util/crypto_helper_rsa.c b/src/util/crypto_helper_rsa.c
index 4098a846..7dd584aa 100644
--- a/src/util/crypto_helper_rsa.c
+++ b/src/util/crypto_helper_rsa.c
@@ -203,23 +203,27 @@ handle_mt_avail (struct 
TALER_CRYPTO_RsaDenominationHelper *dh,
   }
 
   {
-    struct TALER_DenominationPublicKey denom_pub;
+    struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub;
     struct TALER_RsaPubHashP h_rsa;
 
-    denom_pub.cipher = TALER_DENOMINATION_RSA;
-    denom_pub.details.rsa_public_key
+    bs_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
+    bs_pub->cipher = GNUNET_CRYPTO_BSA_RSA;
+    bs_pub->details.rsa_public_key
       = GNUNET_CRYPTO_rsa_public_key_decode (buf,
                                              ntohs (kan->pub_size));
-    if (NULL == denom_pub.details.rsa_public_key)
+    if (NULL == bs_pub->details.rsa_public_key)
     {
       GNUNET_break_op (0);
+      GNUNET_free (bs_pub);
       return GNUNET_SYSERR;
     }
-    GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.details.rsa_public_key,
-                                       &h_rsa.hash);
+    bs_pub->rc = 1;
+    GNUNET_CRYPTO_rsa_public_key_hash (bs_pub->details.rsa_public_key,
+                                       &bs_pub->pub_key_hash);
+    h_rsa.hash = bs_pub->pub_key_hash;
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Received RSA key %s (%s)\n",
-                GNUNET_h2s (&h_rsa.hash),
+                GNUNET_h2s (&bs_pub->pub_key_hash),
                 section_name);
     if (GNUNET_OK !=
         TALER_exchange_secmod_rsa_verify (
@@ -231,7 +235,7 @@ handle_mt_avail (struct TALER_CRYPTO_RsaDenominationHelper 
*dh,
           &kan->secm_sig))
     {
       GNUNET_break_op (0);
-      TALER_denom_pub_free (&denom_pub);
+      GNUNET_CRYPTO_blind_sign_pub_decref (bs_pub);
       return GNUNET_SYSERR;
     }
     dh->dkc (dh->dkc_cls,
@@ -239,10 +243,10 @@ handle_mt_avail (struct 
TALER_CRYPTO_RsaDenominationHelper *dh,
              GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
              GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
              &h_rsa,
-             &denom_pub,
+             bs_pub,
              &kan->secm_pub,
              &kan->secm_sig);
-    TALER_denom_pub_free (&denom_pub);
+    GNUNET_CRYPTO_blind_sign_pub_decref (bs_pub);
   }
   return GNUNET_OK;
 }
@@ -395,7 +399,9 @@ TALER_CRYPTO_helper_rsa_sign (
 {
   enum TALER_ErrorCode ec = TALER_EC_INVALID;
 
-  bs->cipher = TALER_DENOMINATION_INVALID;
+  memset (bs,
+          0,
+          sizeof (*bs));
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Starting signature process\n");
   if (GNUNET_OK !=
@@ -503,6 +509,7 @@ more:
           const struct TALER_CRYPTO_SignResponse *sr =
             (const struct TALER_CRYPTO_SignResponse *) buf;
           struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
+          struct GNUNET_CRYPTO_BlindedSignature *blind_sig;
 
           rsa_signature = GNUNET_CRYPTO_rsa_signature_decode (
             &sr[1],
@@ -518,8 +525,11 @@ more:
                       "Received signature\n");
           ec = TALER_EC_NONE;
           finished = true;
-          bs->cipher = TALER_DENOMINATION_RSA;
-          bs->details.blinded_rsa_signature = rsa_signature;
+          blind_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
+          blind_sig->cipher = GNUNET_CRYPTO_BSA_RSA;
+          blind_sig->rc = 1;
+          blind_sig->details.blinded_rsa_signature = rsa_signature;
+          bs->blinded_sig = blind_sig;
           break;
         }
       case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE:
@@ -597,9 +607,9 @@ end:
 enum TALER_ErrorCode
 TALER_CRYPTO_helper_rsa_batch_sign (
   struct TALER_CRYPTO_RsaDenominationHelper *dh,
-  const struct TALER_CRYPTO_RsaSignRequest *rsrs,
   unsigned int rsrs_length,
-  struct TALER_BlindedDenominationSignature *bss)
+  const struct TALER_CRYPTO_RsaSignRequest rsrs[static rsrs_length],
+  struct TALER_BlindedDenominationSignature bss[static rsrs_length])
 {
   enum TALER_ErrorCode ec = TALER_EC_INVALID;
   unsigned int rpos;
@@ -750,6 +760,7 @@ more:
             const struct TALER_CRYPTO_SignResponse *sr =
               (const struct TALER_CRYPTO_SignResponse *) buf;
             struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
+            struct GNUNET_CRYPTO_BlindedSignature *blind_sig;
 
             rsa_signature = GNUNET_CRYPTO_rsa_signature_decode (
               &sr[1],
@@ -763,8 +774,10 @@ more:
             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                         "Received %u signature\n",
                         wpos);
-            bss[wpos].cipher = TALER_DENOMINATION_RSA;
-            bss[wpos].details.blinded_rsa_signature = rsa_signature;
+            blind_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
+            blind_sig->cipher = GNUNET_CRYPTO_BSA_RSA;
+            blind_sig->details.blinded_rsa_signature = rsa_signature;
+            bss[wpos].blinded_sig = blind_sig;
             wpos++;
             if (wpos == rend)
             {
diff --git a/src/util/denom.c b/src/util/denom.c
index c1c3cdf5..20ee8c00 100644
--- a/src/util/denom.c
+++ b/src/util/denom.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2021, 2022 Taler Systems SA
+  Copyright (C) 2021, 2022, 2023 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -25,60 +25,21 @@
 enum GNUNET_GenericReturnValue
 TALER_denom_priv_create (struct TALER_DenominationPrivateKey *denom_priv,
                          struct TALER_DenominationPublicKey *denom_pub,
-                         enum TALER_DenominationCipher cipher,
+                         enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher,
                          ...)
 {
-  memset (denom_priv,
-          0,
-          sizeof (*denom_priv));
-  memset (denom_pub,
-          0,
-          sizeof (*denom_pub));
-
-  switch (cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  case TALER_DENOMINATION_RSA:
-    {
-      va_list ap;
-      unsigned int bits;
-
-      va_start (ap, cipher);
-      bits = va_arg (ap, unsigned int);
-      va_end (ap);
-      if (bits < 512)
-      {
-        GNUNET_break (0);
-        return GNUNET_SYSERR;
-      }
-      denom_priv->details.rsa_private_key
-        = GNUNET_CRYPTO_rsa_private_key_create (bits);
-    }
-    if (NULL == denom_priv->details.rsa_private_key)
-    {
-      GNUNET_break (0);
-      return GNUNET_SYSERR;
-    }
-    denom_pub->details.rsa_public_key
-      = GNUNET_CRYPTO_rsa_private_key_get_public (
-          denom_priv->details.rsa_private_key);
-    denom_priv->cipher = TALER_DENOMINATION_RSA;
-    denom_pub->cipher = TALER_DENOMINATION_RSA;
-    return GNUNET_OK;
-  case TALER_DENOMINATION_CS:
-    GNUNET_CRYPTO_cs_private_key_generate 
(&denom_priv->details.cs_private_key);
-    GNUNET_CRYPTO_cs_private_key_get_public (
-      &denom_priv->details.cs_private_key,
-      &denom_pub->details.cs_public_key);
-    denom_priv->cipher = TALER_DENOMINATION_CS;
-    denom_pub->cipher = TALER_DENOMINATION_CS;
-    return GNUNET_OK;
-  default:
-    GNUNET_break (0);
-  }
-  return GNUNET_SYSERR;
+  enum GNUNET_GenericReturnValue ret;
+  va_list ap;
+
+  va_start (ap,
+            cipher);
+  ret = GNUNET_CRYPTO_blind_sign_keys_create_va (
+    &denom_priv->bsign_priv_key,
+    &denom_pub->bsign_pub_key,
+    cipher,
+    ap);
+  va_end (ap);
+  return ret;
 }
 
 
@@ -88,57 +49,13 @@ TALER_denom_sign_blinded (struct 
TALER_BlindedDenominationSignature *denom_sig,
                           bool for_melt,
                           const struct TALER_BlindedPlanchet *blinded_planchet)
 {
-  memset (denom_sig,
-          0,
-          sizeof (*denom_sig));
-  if (blinded_planchet->cipher != denom_priv->cipher)
-  {
-    GNUNET_break (0);
+  denom_sig->blinded_sig
+    = GNUNET_CRYPTO_blind_sign (denom_priv->bsign_priv_key,
+                                for_melt ? "rm" : "rw",
+                                blinded_planchet->blinded_message);
+  if (NULL == denom_sig->blinded_sig)
     return GNUNET_SYSERR;
-  }
-  switch (denom_priv->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  case TALER_DENOMINATION_RSA:
-    denom_sig->details.blinded_rsa_signature
-      = GNUNET_CRYPTO_rsa_sign_blinded (
-          denom_priv->details.rsa_private_key,
-          blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
-          blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size);
-    if (NULL == denom_sig->details.blinded_rsa_signature)
-    {
-      GNUNET_break (0);
-      return GNUNET_SYSERR;
-    }
-    denom_sig->cipher = TALER_DENOMINATION_RSA;
-    return GNUNET_OK;
-  case TALER_DENOMINATION_CS:
-    {
-      struct GNUNET_CRYPTO_CsRSecret r[2];
-
-      GNUNET_CRYPTO_cs_r_derive (
-        &blinded_planchet->details.cs_blinded_planchet.nonce.nonce,
-        for_melt ? "rm" : "rw",
-        &denom_priv->details.cs_private_key,
-        r);
-      denom_sig->details.blinded_cs_answer.b =
-        GNUNET_CRYPTO_cs_sign_derive (&denom_priv->details.cs_private_key,
-                                      r,
-                                      blinded_planchet->details.
-                                      cs_blinded_planchet.c,
-                                      &blinded_planchet->details.
-                                      cs_blinded_planchet.nonce.nonce,
-                                      &denom_sig->details.blinded_cs_answer.
-                                      s_scalar);
-      denom_sig->cipher = TALER_DENOMINATION_CS;
-    }
-    return GNUNET_OK;
-  default:
-    GNUNET_break (0);
-  }
-  return GNUNET_SYSERR;
+  return GNUNET_OK;
 }
 
 
@@ -146,82 +63,21 @@ enum GNUNET_GenericReturnValue
 TALER_denom_sig_unblind (
   struct TALER_DenominationSignature *denom_sig,
   const struct TALER_BlindedDenominationSignature *bdenom_sig,
-  const union TALER_DenominationBlindingKeyP *bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *bks,
   const struct TALER_CoinPubHashP *c_hash,
   const struct TALER_ExchangeWithdrawValues *alg_values,
   const struct TALER_DenominationPublicKey *denom_pub)
 {
-  if (bdenom_sig->cipher != denom_pub->cipher)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  switch (denom_pub->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    GNUNET_break (0);
+  denom_sig->unblinded_sig
+    = GNUNET_CRYPTO_blind_sig_unblind (bdenom_sig->blinded_sig,
+                                       bks,
+                                       c_hash,
+                                       sizeof (*c_hash),
+                                       alg_values->blinding_inputs,
+                                       denom_pub->bsign_pub_key);
+  if (NULL == denom_sig->unblinded_sig)
     return GNUNET_SYSERR;
-  case TALER_DENOMINATION_RSA:
-    denom_sig->details.rsa_signature
-      = GNUNET_CRYPTO_rsa_unblind (
-          bdenom_sig->details.blinded_rsa_signature,
-          &bks->rsa_bks,
-          denom_pub->details.rsa_public_key);
-    if (NULL == denom_sig->details.rsa_signature)
-    {
-      GNUNET_break (0);
-      return GNUNET_SYSERR;
-    }
-    denom_sig->cipher = TALER_DENOMINATION_RSA;
-    return GNUNET_OK;
-  case TALER_DENOMINATION_CS:
-    {
-      struct GNUNET_CRYPTO_CsBlindingSecret bs[2];
-      struct GNUNET_CRYPTO_CsC c[2];
-      struct TALER_DenominationCSPublicRPairP r_pub_blind;
-
-      GNUNET_CRYPTO_cs_blinding_secrets_derive (&bks->nonce,
-                                                bs);
-      GNUNET_CRYPTO_cs_calc_blinded_c (
-        bs,
-        alg_values->details.cs_values.r_pub,
-        &denom_pub->details.cs_public_key,
-        &c_hash->hash,
-        sizeof(struct GNUNET_HashCode),
-        c,
-        r_pub_blind.r_pub);
-      denom_sig->details.cs_signature.r_point
-        = r_pub_blind.r_pub[bdenom_sig->details.blinded_cs_answer.b];
-      GNUNET_CRYPTO_cs_unblind 
(&bdenom_sig->details.blinded_cs_answer.s_scalar,
-                                &bs[bdenom_sig->details.blinded_cs_answer.b],
-                                &denom_sig->details.cs_signature.s_scalar);
-      denom_sig->cipher = TALER_DENOMINATION_CS;
-      return GNUNET_OK;
-    }
-  default:
-    GNUNET_break (0);
-  }
-  return GNUNET_SYSERR;
-}
-
-
-void
-TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa,
-                    struct TALER_RsaPubHashP *h_rsa)
-{
-  GNUNET_CRYPTO_rsa_public_key_hash (rsa,
-                                     &h_rsa->hash);
-
-}
-
-
-void
-TALER_cs_pub_hash (const struct GNUNET_CRYPTO_CsPublicKey *cs,
-                   struct TALER_CsPubHashP *h_cs)
-{
-  GNUNET_CRYPTO_hash (cs,
-                      sizeof(*cs),
-                      &h_cs->hash);
+  return GNUNET_OK;
 }
 
 
@@ -229,9 +85,11 @@ void
 TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub,
                       struct TALER_DenominationHashP *denom_hash)
 {
+  struct GNUNET_CRYPTO_BlindSignPublicKey *bsp
+    = denom_pub->bsign_pub_key;
   uint32_t opt[2] = {
     htonl (denom_pub->age_mask.bits),
-    htonl ((uint32_t) denom_pub->cipher)
+    htonl ((uint32_t) bsp->cipher)
   };
   struct GNUNET_HashContext *hc;
 
@@ -239,15 +97,15 @@ TALER_denom_pub_hash (const struct 
TALER_DenominationPublicKey *denom_pub,
   GNUNET_CRYPTO_hash_context_read (hc,
                                    opt,
                                    sizeof (opt));
-  switch (denom_pub->cipher)
+  switch (bsp->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     {
       void *buf;
       size_t blen;
 
       blen = GNUNET_CRYPTO_rsa_public_key_encode (
-        denom_pub->details.rsa_public_key,
+        bsp->details.rsa_public_key,
         &buf);
       GNUNET_CRYPTO_hash_context_read (hc,
                                        buf,
@@ -255,10 +113,10 @@ TALER_denom_pub_hash (const struct 
TALER_DenominationPublicKey *denom_pub,
       GNUNET_free (buf);
     }
     break;
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     GNUNET_CRYPTO_hash_context_read (hc,
-                                     &denom_pub->details.cs_public_key,
-                                     sizeof(denom_pub->details.cs_public_key));
+                                     &bsp->details.cs_public_key,
+                                     sizeof(bsp->details.cs_public_key));
     break;
   default:
     GNUNET_assert (0);
@@ -268,37 +126,24 @@ TALER_denom_pub_hash (const struct 
TALER_DenominationPublicKey *denom_pub,
 }
 
 
-void
-TALER_denom_priv_to_pub (const struct TALER_DenominationPrivateKey *denom_priv,
-                         const struct TALER_AgeMask age_mask,
-                         struct TALER_DenominationPublicKey *denom_pub)
+const struct TALER_ExchangeWithdrawValues *
+TALER_denom_ewv_rsa_singleton ()
 {
-  switch (denom_priv->cipher)
-  {
-  case TALER_DENOMINATION_RSA:
-    denom_pub->cipher = TALER_DENOMINATION_RSA;
-    denom_pub->age_mask = age_mask;
-    denom_pub->details.rsa_public_key
-      = GNUNET_CRYPTO_rsa_private_key_get_public (
-          denom_priv->details.rsa_private_key);
-    return;
-  case TALER_DENOMINATION_CS:
-    denom_pub->cipher = TALER_DENOMINATION_CS;
-    denom_pub->age_mask = age_mask;
-    GNUNET_CRYPTO_cs_private_key_get_public (
-      &denom_priv->details.cs_private_key,
-      &denom_pub->details.cs_public_key);
-    return;
-  default:
-    GNUNET_assert (0);
-  }
+  static struct GNUNET_CRYPTO_BlindingInputValues bi = {
+    .cipher = GNUNET_CRYPTO_BSA_RSA
+  };
+  static struct TALER_ExchangeWithdrawValues alg_values = {
+    .blinding_inputs = &bi
+  };
+  return &alg_values;
 }
 
 
 enum GNUNET_GenericReturnValue
 TALER_denom_blind (
   const struct TALER_DenominationPublicKey *dk,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
+  const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
   const struct TALER_AgeCommitmentHash *ach,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   const struct TALER_ExchangeWithdrawValues *alg_values,
@@ -308,44 +153,16 @@ TALER_denom_blind (
   TALER_coin_pub_hash (coin_pub,
                        ach,
                        c_hash);
-  switch (dk->cipher)
-  {
-  case TALER_DENOMINATION_RSA:
-    blinded_planchet->cipher = dk->cipher;
-    if (GNUNET_YES !=
-        GNUNET_CRYPTO_rsa_blind (
-          &c_hash->hash,
-          &coin_bks->rsa_bks,
-          dk->details.rsa_public_key,
-          &blinded_planchet->details.rsa_blinded_planchet.blinded_msg,
-          &blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size))
-    {
-      GNUNET_break (0);
-      return GNUNET_SYSERR;
-    }
-    return GNUNET_OK;
-  case TALER_DENOMINATION_CS:
-    {
-      struct TALER_DenominationCSPublicRPairP blinded_r_pub;
-      struct GNUNET_CRYPTO_CsBlindingSecret bs[2];
-
-      blinded_planchet->cipher = TALER_DENOMINATION_CS;
-      GNUNET_CRYPTO_cs_blinding_secrets_derive (&coin_bks->nonce,
-                                                bs);
-      GNUNET_CRYPTO_cs_calc_blinded_c (
-        bs,
-        alg_values->details.cs_values.r_pub,
-        &dk->details.cs_public_key,
-        c_hash,
-        sizeof(*c_hash),
-        blinded_planchet->details.cs_blinded_planchet.c,
-        blinded_r_pub.r_pub);
-      return GNUNET_OK;
-    }
-  default:
-    GNUNET_break (0);
+  blinded_planchet->blinded_message
+    = GNUNET_CRYPTO_message_blind_to_sign (dk->bsign_pub_key,
+                                           coin_bks,
+                                           nonce,
+                                           c_hash,
+                                           sizeof (*c_hash),
+                                           alg_values->blinding_inputs);
+  if (NULL == blinded_planchet->blinded_message)
     return GNUNET_SYSERR;
-  }
+  return GNUNET_OK;
 }
 
 
@@ -354,111 +171,34 @@ TALER_denom_pub_verify (const struct 
TALER_DenominationPublicKey *denom_pub,
                         const struct TALER_DenominationSignature *denom_sig,
                         const struct TALER_CoinPubHashP *c_hash)
 {
-  if (denom_pub->cipher != denom_sig->cipher)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  switch (denom_pub->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    GNUNET_break (0);
-    return GNUNET_NO;
-  case TALER_DENOMINATION_RSA:
-    if (GNUNET_OK !=
-        GNUNET_CRYPTO_rsa_verify (&c_hash->hash,
-                                  denom_sig->details.rsa_signature,
-                                  denom_pub->details.rsa_public_key))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Coin signature is invalid\n");
-      return GNUNET_NO;
-    }
-    return GNUNET_YES;
-  case TALER_DENOMINATION_CS:
-    if (GNUNET_OK !=
-        GNUNET_CRYPTO_cs_verify (&denom_sig->details.cs_signature,
-                                 &denom_pub->details.cs_public_key,
-                                 &c_hash->hash,
-                                 sizeof(struct GNUNET_HashCode)))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Coin signature is invalid\n");
-      return GNUNET_NO;
-    }
-    return GNUNET_YES;
-  default:
-    GNUNET_assert (0);
-  }
+  return GNUNET_CRYPTO_blind_sig_verify (denom_pub->bsign_pub_key,
+                                         denom_sig->unblinded_sig,
+                                         c_hash,
+                                         sizeof (*c_hash));
 }
 
 
 void
 TALER_denom_pub_free (struct TALER_DenominationPublicKey *denom_pub)
 {
-  switch (denom_pub->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    return;
-  case TALER_DENOMINATION_RSA:
-    if (NULL != denom_pub->details.rsa_public_key)
-    {
-      GNUNET_CRYPTO_rsa_public_key_free (denom_pub->details.rsa_public_key);
-      denom_pub->details.rsa_public_key = NULL;
-    }
-    denom_pub->cipher = TALER_DENOMINATION_INVALID;
-    return;
-  case TALER_DENOMINATION_CS:
-    return;
-  default:
-    GNUNET_assert (0);
-  }
+  GNUNET_CRYPTO_blind_sign_pub_decref (denom_pub->bsign_pub_key);
+  denom_pub->bsign_pub_key = NULL;
 }
 
 
 void
 TALER_denom_priv_free (struct TALER_DenominationPrivateKey *denom_priv)
 {
-  switch (denom_priv->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    return;
-  case TALER_DENOMINATION_RSA:
-    if (NULL != denom_priv->details.rsa_private_key)
-    {
-      GNUNET_CRYPTO_rsa_private_key_free (denom_priv->details.rsa_private_key);
-      denom_priv->details.rsa_private_key = NULL;
-    }
-    denom_priv->cipher = TALER_DENOMINATION_INVALID;
-    return;
-  case TALER_DENOMINATION_CS:
-    return;
-  default:
-    GNUNET_assert (0);
-  }
+  GNUNET_CRYPTO_blind_sign_priv_decref (denom_priv->bsign_priv_key);
+  denom_priv->bsign_priv_key = NULL;
 }
 
 
 void
 TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig)
 {
-  switch (denom_sig->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    return;
-  case TALER_DENOMINATION_RSA:
-    if (NULL != denom_sig->details.rsa_signature)
-    {
-      GNUNET_CRYPTO_rsa_signature_free (denom_sig->details.rsa_signature);
-      denom_sig->details.rsa_signature = NULL;
-    }
-    denom_sig->cipher = TALER_DENOMINATION_INVALID;
-    return;
-  case TALER_DENOMINATION_CS:
-    return;
-  default:
-    GNUNET_assert (0);
-  }
+  GNUNET_CRYPTO_unblinded_sig_decref (denom_sig->unblinded_sig);
+  denom_sig->unblinded_sig = NULL;
 }
 
 
@@ -466,24 +206,8 @@ void
 TALER_blinded_denom_sig_free (
   struct TALER_BlindedDenominationSignature *denom_sig)
 {
-  switch (denom_sig->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    return;
-  case TALER_DENOMINATION_RSA:
-    if (NULL != denom_sig->details.blinded_rsa_signature)
-    {
-      GNUNET_CRYPTO_rsa_signature_free (
-        denom_sig->details.blinded_rsa_signature);
-      denom_sig->details.blinded_rsa_signature = NULL;
-    }
-    denom_sig->cipher = TALER_DENOMINATION_INVALID;
-    return;
-  case TALER_DENOMINATION_CS:
-    return;
-  default:
-    GNUNET_assert (0);
-  }
+  GNUNET_CRYPTO_blinded_sig_decref (denom_sig->blinded_sig);
+  denom_sig->blinded_sig = NULL;
 }
 
 
@@ -491,19 +215,8 @@ void
 TALER_denom_pub_deep_copy (struct TALER_DenominationPublicKey *denom_dst,
                            const struct TALER_DenominationPublicKey *denom_src)
 {
-  *denom_dst = *denom_src; /* shallow copy */
-  switch (denom_src->cipher)
-  {
-  case TALER_DENOMINATION_RSA:
-    denom_dst->details.rsa_public_key
-      = GNUNET_CRYPTO_rsa_public_key_dup (
-          denom_src->details.rsa_public_key);
-    return;
-  case TALER_DENOMINATION_CS:
-    return;
-  default:
-    GNUNET_assert (0);
-  }
+  denom_dst->bsign_pub_key
+    = GNUNET_CRYPTO_bsign_pub_incref (denom_src->bsign_pub_key);
 }
 
 
@@ -511,21 +224,8 @@ void
 TALER_denom_sig_deep_copy (struct TALER_DenominationSignature *denom_dst,
                            const struct TALER_DenominationSignature *denom_src)
 {
-  *denom_dst = *denom_src; /* shallow copy */
-  switch (denom_src->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    return;
-  case TALER_DENOMINATION_RSA:
-    denom_dst->details.rsa_signature
-      = GNUNET_CRYPTO_rsa_signature_dup (
-          denom_src->details.rsa_signature);
-    return;
-  case TALER_DENOMINATION_CS:
-    return;
-  default:
-    GNUNET_assert (0);
-  }
+  denom_dst->unblinded_sig
+    = GNUNET_CRYPTO_ub_sig_incref (denom_src->unblinded_sig);
 }
 
 
@@ -534,21 +234,8 @@ TALER_blinded_denom_sig_deep_copy (
   struct TALER_BlindedDenominationSignature *denom_dst,
   const struct TALER_BlindedDenominationSignature *denom_src)
 {
-  *denom_dst = *denom_src; /* shallow copy */
-  switch (denom_src->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    return;
-  case TALER_DENOMINATION_RSA:
-    denom_dst->details.blinded_rsa_signature
-      = GNUNET_CRYPTO_rsa_signature_dup (
-          denom_src->details.blinded_rsa_signature);
-    return;
-  case TALER_DENOMINATION_CS:
-    return;
-  default:
-    GNUNET_assert (0);
-  }
+  denom_dst->blinded_sig
+    = GNUNET_CRYPTO_blind_sig_incref (denom_src->blinded_sig);
 }
 
 
@@ -556,24 +243,14 @@ int
 TALER_denom_pub_cmp (const struct TALER_DenominationPublicKey *denom1,
                      const struct TALER_DenominationPublicKey *denom2)
 {
-  if (denom1->cipher != denom2->cipher)
-    return (denom1->cipher > denom2->cipher) ? 1 : -1;
+  if (denom1->bsign_pub_key->cipher !=
+      denom2->bsign_pub_key->cipher)
+    return (denom1->bsign_pub_key->cipher >
+            denom2->bsign_pub_key->cipher) ? 1 : -1;
   if (denom1->age_mask.bits != denom2->age_mask.bits)
     return (denom1->age_mask.bits > denom2->age_mask.bits) ? 1 : -1;
-  switch (denom1->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    return 0;
-  case TALER_DENOMINATION_RSA:
-    return GNUNET_CRYPTO_rsa_public_key_cmp (denom1->details.rsa_public_key,
-                                             denom2->details.rsa_public_key);
-  case TALER_DENOMINATION_CS:
-    return GNUNET_memcmp (&denom1->details.cs_public_key,
-                          &denom2->details.cs_public_key);
-  default:
-    GNUNET_assert (0);
-  }
-  return -2;
+  return GNUNET_CRYPTO_bsign_pub_cmp (denom1->bsign_pub_key,
+                                      denom2->bsign_pub_key);
 }
 
 
@@ -581,22 +258,8 @@ int
 TALER_denom_sig_cmp (const struct TALER_DenominationSignature *sig1,
                      const struct TALER_DenominationSignature *sig2)
 {
-  if (sig1->cipher != sig2->cipher)
-    return (sig1->cipher > sig2->cipher) ? 1 : -1;
-  switch (sig1->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    return 0;
-  case TALER_DENOMINATION_RSA:
-    return GNUNET_CRYPTO_rsa_signature_cmp (sig1->details.rsa_signature,
-                                            sig2->details.rsa_signature);
-  case TALER_DENOMINATION_CS:
-    return GNUNET_memcmp (&sig1->details.cs_signature,
-                          &sig2->details.cs_signature);
-  default:
-    GNUNET_assert (0);
-  }
-  return -2;
+  return GNUNET_CRYPTO_ub_sig_cmp (sig1->unblinded_sig,
+                                   sig1->unblinded_sig);
 }
 
 
@@ -605,27 +268,8 @@ TALER_blinded_planchet_cmp (
   const struct TALER_BlindedPlanchet *bp1,
   const struct TALER_BlindedPlanchet *bp2)
 {
-  if (bp1->cipher != bp2->cipher)
-    return (bp1->cipher > bp2->cipher) ? 1 : -1;
-  switch (bp1->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    return 0;
-  case TALER_DENOMINATION_RSA:
-    if (bp1->details.rsa_blinded_planchet.blinded_msg_size !=
-        bp2->details.rsa_blinded_planchet.blinded_msg_size)
-      return (bp1->details.rsa_blinded_planchet.blinded_msg_size >
-              bp2->details.rsa_blinded_planchet.blinded_msg_size) ? 1 : -1;
-    return memcmp (bp1->details.rsa_blinded_planchet.blinded_msg,
-                   bp2->details.rsa_blinded_planchet.blinded_msg,
-                   bp1->details.rsa_blinded_planchet.blinded_msg_size);
-  case TALER_DENOMINATION_CS:
-    return GNUNET_memcmp (&bp1->details.cs_blinded_planchet,
-                          &bp2->details.cs_blinded_planchet);
-  default:
-    GNUNET_assert (0);
-  }
-  return -2;
+  return GNUNET_CRYPTO_blinded_message_cmp (bp1->blinded_message,
+                                            bp2->blinded_message);
 }
 
 
@@ -634,22 +278,8 @@ TALER_blinded_denom_sig_cmp (
   const struct TALER_BlindedDenominationSignature *sig1,
   const struct TALER_BlindedDenominationSignature *sig2)
 {
-  if (sig1->cipher != sig2->cipher)
-    return (sig1->cipher > sig2->cipher) ? 1 : -1;
-  switch (sig1->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    return 0;
-  case TALER_DENOMINATION_RSA:
-    return GNUNET_CRYPTO_rsa_signature_cmp 
(sig1->details.blinded_rsa_signature,
-                                            
sig2->details.blinded_rsa_signature);
-  case TALER_DENOMINATION_CS:
-    return GNUNET_memcmp (&sig1->details.blinded_cs_answer,
-                          &sig2->details.blinded_cs_answer);
-  default:
-    GNUNET_assert (0);
-  }
-  return -2;
+  return GNUNET_CRYPTO_blind_sig_cmp (sig1->blinded_sig,
+                                      sig1->blinded_sig);
 }
 
 
@@ -657,31 +287,31 @@ void
 TALER_blinded_planchet_hash_ (const struct TALER_BlindedPlanchet *bp,
                               struct GNUNET_HashContext *hash_context)
 {
-  uint32_t cipher = htonl (bp->cipher);
+  const struct GNUNET_CRYPTO_BlindedMessage *bm = bp->blinded_message;
+  uint32_t cipher = htonl (bm->cipher);
 
   GNUNET_CRYPTO_hash_context_read (hash_context,
                                    &cipher,
                                    sizeof (cipher));
-  switch (bp->cipher)
+  switch (bm->cipher)
   {
-  case TALER_DENOMINATION_INVALID:
-    break;
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    return;
+  case GNUNET_CRYPTO_BSA_RSA:
     GNUNET_CRYPTO_hash_context_read (
       hash_context,
-      bp->details.rsa_blinded_planchet.blinded_msg,
-      bp->details.rsa_blinded_planchet.blinded_msg_size);
-    break;
-  case TALER_DENOMINATION_CS:
+      bm->details.rsa_blinded_message.blinded_msg,
+      bm->details.rsa_blinded_message.blinded_msg_size);
+    return;
+  case GNUNET_CRYPTO_BSA_CS:
     GNUNET_CRYPTO_hash_context_read (
       hash_context,
-      &bp->details.cs_blinded_planchet,
-      sizeof (bp->details.cs_blinded_planchet));
-    break;
-  default:
-    GNUNET_assert (0);
-    break;
+      &bm->details.cs_blinded_message,
+      sizeof (bm->details.cs_blinded_message));
+    return;
   }
+  GNUNET_assert (0);
 }
 
 
@@ -689,14 +319,17 @@ void
 TALER_planchet_blinding_secret_create (
   const struct TALER_PlanchetMasterSecretP *ps,
   const struct TALER_ExchangeWithdrawValues *alg_values,
-  union TALER_DenominationBlindingKeyP *bks)
+  union GNUNET_CRYPTO_BlindingSecretP *bks)
 {
-  switch (alg_values->cipher)
+  const struct GNUNET_CRYPTO_BlindingInputValues *bi =
+    alg_values->blinding_inputs;
+
+  switch (bi->cipher)
   {
-  case TALER_DENOMINATION_INVALID:
+  case GNUNET_CRYPTO_BSA_INVALID:
     GNUNET_break (0);
     return;
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_RSA:
     GNUNET_assert (GNUNET_YES ==
                    GNUNET_CRYPTO_kdf (&bks->rsa_bks,
                                       sizeof (bks->rsa_bks),
@@ -707,7 +340,7 @@ TALER_planchet_blinding_secret_create (
                                       NULL,
                                       0));
     return;
-  case TALER_DENOMINATION_CS:
+  case GNUNET_CRYPTO_BSA_CS:
     GNUNET_assert (GNUNET_YES ==
                    GNUNET_CRYPTO_kdf (&bks->nonce,
                                       sizeof (bks->nonce),
@@ -715,14 +348,13 @@ TALER_planchet_blinding_secret_create (
                                       strlen ("bseed"),
                                       ps,
                                       sizeof(*ps),
-                                      &alg_values->details.cs_values,
-                                      sizeof(alg_values->details.cs_values),
+                                      &bi->details.cs_values,
+                                      sizeof(bi->details.cs_values),
                                       NULL,
                                       0));
     return;
-  default:
-    GNUNET_break (0);
   }
+  GNUNET_assert (0);
 }
 
 
@@ -732,9 +364,18 @@ TALER_planchet_setup_coin_priv (
   const struct TALER_ExchangeWithdrawValues *alg_values,
   struct TALER_CoinSpendPrivateKeyP *coin_priv)
 {
-  switch (alg_values->cipher)
+  const struct GNUNET_CRYPTO_BlindingInputValues *bi
+    = alg_values->blinding_inputs;
+
+  switch (bi->cipher)
   {
-  case TALER_DENOMINATION_RSA:
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    memset (coin_priv,
+            0,
+            sizeof (*coin_priv));
+    return;
+  case GNUNET_CRYPTO_BSA_RSA:
     GNUNET_assert (GNUNET_YES ==
                    GNUNET_CRYPTO_kdf (coin_priv,
                                       sizeof (*coin_priv),
@@ -744,8 +385,8 @@ TALER_planchet_setup_coin_priv (
                                       sizeof(*ps),
                                       NULL,
                                       0));
-    break;
-  case TALER_DENOMINATION_CS:
+    return;
+  case GNUNET_CRYPTO_BSA_CS:
     GNUNET_assert (GNUNET_YES ==
                    GNUNET_CRYPTO_kdf (coin_priv,
                                       sizeof (*coin_priv),
@@ -753,37 +394,21 @@ TALER_planchet_setup_coin_priv (
                                       strlen ("coin"),
                                       ps,
                                       sizeof(*ps),
-                                      &alg_values->details.cs_values,
-                                      sizeof(alg_values->details.cs_values),
+                                      &bi->details.cs_values,
+                                      sizeof(bi->details.cs_values),
                                       NULL,
                                       0));
-    break;
-  default:
-    GNUNET_break (0);
     return;
   }
+  GNUNET_assert (0);
 }
 
 
 void
 TALER_blinded_planchet_free (struct TALER_BlindedPlanchet *blinded_planchet)
 {
-  switch (blinded_planchet->cipher)
-  {
-  case TALER_DENOMINATION_INVALID:
-    GNUNET_break (0);
-    return;
-  case TALER_DENOMINATION_RSA:
-    GNUNET_free (blinded_planchet->details.rsa_blinded_planchet.blinded_msg);
-    return;
-  case TALER_DENOMINATION_CS:
-    memset (blinded_planchet,
-            0,
-            sizeof (*blinded_planchet));
-    /* nothing to do for CS */
-    return;
-  }
-  GNUNET_assert (0);
+  GNUNET_CRYPTO_blinded_message_decref (blinded_planchet->blinded_message);
+  blinded_planchet->blinded_message = NULL;
 }
 
 
diff --git a/src/util/taler-exchange-secmod-cs.c 
b/src/util/taler-exchange-secmod-cs.c
index ed0eba15..a9696ee8 100644
--- a/src/util/taler-exchange-secmod-cs.c
+++ b/src/util/taler-exchange-secmod-cs.c
@@ -269,7 +269,7 @@ struct BatchJob
       /**
        * Result with the signature.
        */
-      struct TALER_BlindedDenominationCsSignAnswer cs_answer;
+      struct GNUNET_CRYPTO_CsBlindSignature cs_answer;
     } sign;
 
     /**
@@ -285,7 +285,7 @@ struct BatchJob
       /**
        * Pair of points to return.
        */
-      struct TALER_DenominationCSPublicRPairP rpairp;
+      struct GNUNET_CRYPTO_CSPublicRPairP rpairp;
 
     } rderive;
 
@@ -433,7 +433,7 @@ generate_response (struct DenominationKey *dk)
 /**
  * Do the actual signing work.
  *
- * @param h_cs key to sign with
+ * @param h_cs hash of key to sign with
  * @param planchet message to sign
  * @param for_melt true if for melting
  * @param[out] cs_sigp set to the CS signature
@@ -441,9 +441,9 @@ generate_response (struct DenominationKey *dk)
  */
 static enum TALER_ErrorCode
 do_sign (const struct TALER_CsPubHashP *h_cs,
-         const struct TALER_BlindedCsPlanchet *planchet,
+         const struct GNUNET_CRYPTO_CsBlindedMessage *planchet,
          bool for_melt,
-         struct TALER_BlindedDenominationCsSignAnswer *cs_sigp)
+         struct GNUNET_CRYPTO_CsBlindSignature *cs_sigp)
 {
   struct GNUNET_CRYPTO_CsRSecret r[2];
   struct DenominationKey *dk;
@@ -473,15 +473,14 @@ do_sign (const struct TALER_CsPubHashP *h_cs,
   GNUNET_assert (dk->rc < UINT_MAX);
   dk->rc++;
   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
-  GNUNET_CRYPTO_cs_r_derive (&planchet->nonce.nonce,
+  GNUNET_CRYPTO_cs_r_derive (&planchet->nonce,
                              for_melt ? "rm" : "rw",
                              &dk->denom_priv,
                              r);
-  cs_sigp->b = GNUNET_CRYPTO_cs_sign_derive (&dk->denom_priv,
-                                             r,
-                                             planchet->c,
-                                             &planchet->nonce.nonce,
-                                             &cs_sigp->s_scalar);
+  GNUNET_CRYPTO_cs_sign_derive (&dk->denom_priv,
+                                r,
+                                planchet,
+                                cs_sigp);
   GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
   GNUNET_assert (dk->rc > 0);
   dk->rc--;
@@ -543,14 +542,14 @@ fail_derive (struct TES_Client *client,
  */
 static enum GNUNET_GenericReturnValue
 send_signature (struct TES_Client *client,
-                const struct TALER_BlindedDenominationCsSignAnswer *cs_answer)
+                const struct GNUNET_CRYPTO_CsBlindSignature *cs_answer)
 {
   struct TALER_CRYPTO_SignResponse sres;
 
   sres.header.size = htons (sizeof (sres));
   sres.header.type = htons (TALER_HELPER_CS_MT_RES_SIGNATURE);
-  sres.reserved = htonl (0);
-  sres.cs_answer = *cs_answer;
+  sres.b = htonl (cs_answer->b);
+  sres.cs_answer = cs_answer->s_scalar;
   return TES_transmit (client->csock,
                        &sres.header);
 }
@@ -569,13 +568,13 @@ static enum GNUNET_GenericReturnValue
 handle_sign_request (struct TES_Client *client,
                      const struct TALER_CRYPTO_CsSignRequestMessage *sr)
 {
-  struct TALER_BlindedDenominationCsSignAnswer cs_answer;
+  struct GNUNET_CRYPTO_CsBlindSignature cs_answer;
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
   enum TALER_ErrorCode ec;
   enum GNUNET_GenericReturnValue ret;
 
   ec = do_sign (&sr->h_cs,
-                &sr->planchet,
+                &sr->message,
                 (0 != ntohl (sr->for_melt)),
                 &cs_answer);
   if (TALER_EC_NONE != ec)
@@ -605,12 +604,12 @@ handle_sign_request (struct TES_Client *client,
  */
 static enum TALER_ErrorCode
 do_derive (const struct TALER_CsPubHashP *h_cs,
-           const struct TALER_CsNonce *nonce,
+           const struct GNUNET_CRYPTO_CsSessionNonce *nonce,
            bool for_melt,
-           struct TALER_DenominationCSPublicRPairP *rpairp)
+           struct GNUNET_CRYPTO_CSPublicRPairP *rpairp)
 {
   struct DenominationKey *dk;
-  struct TALER_DenominationCSPrivateRPairP r_priv;
+  struct GNUNET_CRYPTO_CSPrivateRPairP r_priv;
 
   GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
   dk = GNUNET_CONTAINER_multihashmap_get (keys,
@@ -637,7 +636,7 @@ do_derive (const struct TALER_CsPubHashP *h_cs,
   GNUNET_assert (dk->rc < UINT_MAX);
   dk->rc++;
   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
-  GNUNET_CRYPTO_cs_r_derive (&nonce->nonce,
+  GNUNET_CRYPTO_cs_r_derive (nonce,
                              for_melt ? "rm" : "rw",
                              &dk->denom_priv,
                              r_priv.r);
@@ -662,10 +661,10 @@ do_derive (const struct TALER_CsPubHashP *h_cs,
  */
 static enum GNUNET_GenericReturnValue
 send_derivation (struct TES_Client *client,
-                 const struct TALER_DenominationCSPublicRPairP *r_pub)
+                 const struct GNUNET_CRYPTO_CSPublicRPairP *r_pub)
 {
   struct TALER_CRYPTO_RDeriveResponse rdr = {
-    .header.size = htons (sizeof (struct TALER_CRYPTO_RDeriveResponse)),
+    .header.size = htons (sizeof (rdr)),
     .header.type = htons (TALER_HELPER_CS_MT_RES_RDERIVE),
     .r_pub = *r_pub
   };
@@ -776,7 +775,7 @@ worker (void *cls)
             = bj->details.sign.sr;
 
           bj->ec = do_sign (&sr->h_cs,
-                            &sr->planchet,
+                            &sr->message,
                             (0 != ntohl (sr->for_melt)),
                             &bj->details.sign.cs_answer);
           break;
@@ -1093,8 +1092,9 @@ setup_key (struct DenominationKey *dk,
   GNUNET_CRYPTO_cs_private_key_generate (&priv);
   GNUNET_CRYPTO_cs_private_key_get_public (&priv,
                                            &pub);
-  TALER_cs_pub_hash (&pub,
-                     &dk->h_cs);
+  GNUNET_CRYPTO_hash (&pub,
+                      sizeof (pub),
+                      &dk->h_cs.hash);
   GNUNET_asprintf (&dk->filename,
                    "%s/%s/%llu",
                    keydir,
@@ -1242,7 +1242,7 @@ static enum GNUNET_GenericReturnValue
 handle_r_derive_request (struct TES_Client *client,
                          const struct TALER_CRYPTO_CsRDeriveRequest *rdr)
 {
-  struct TALER_DenominationCSPublicRPairP r_pub;
+  struct GNUNET_CRYPTO_CSPublicRPairP r_pub;
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
   enum TALER_ErrorCode ec;
   enum GNUNET_GenericReturnValue ret;
@@ -1773,20 +1773,19 @@ parse_key (struct Denomination *denom,
     return;
   }
   {
-    struct GNUNET_CRYPTO_CsPublicKey pub;
     struct DenominationKey *dk;
     struct DenominationKey *before;
 
-    GNUNET_CRYPTO_cs_private_key_get_public (priv,
-                                             &pub);
     dk = GNUNET_new (struct DenominationKey);
     dk->denom_priv = *priv;
     dk->denom = denom;
     dk->anchor = anchor;
     dk->filename = GNUNET_strdup (filename);
-    TALER_cs_pub_hash (&pub,
-                       &dk->h_cs);
-    dk->denom_pub = pub;
+    GNUNET_CRYPTO_cs_private_key_get_public (priv,
+                                             &dk->denom_pub);
+    GNUNET_CRYPTO_hash (&dk->denom_pub,
+                        sizeof (dk->denom_pub),
+                        &dk->h_cs.hash);
     generate_response (dk);
     if (GNUNET_OK !=
         GNUNET_CONTAINER_multihashmap_put (
@@ -1808,7 +1807,9 @@ parse_key (struct Denomination *denom,
          NULL != pos;
          pos = pos->next)
     {
-      if (GNUNET_TIME_timestamp_cmp (pos->anchor, >, anchor))
+      if (GNUNET_TIME_timestamp_cmp (pos->anchor,
+                                     >,
+                                     anchor))
         break;
       before = pos;
     }
diff --git a/src/util/taler-exchange-secmod-cs.h 
b/src/util/taler-exchange-secmod-cs.h
index fd550efb..0321335d 100644
--- a/src/util/taler-exchange-secmod-cs.h
+++ b/src/util/taler-exchange-secmod-cs.h
@@ -136,9 +136,9 @@ struct TALER_CRYPTO_CsSignRequestMessage
   struct TALER_CsPubHashP h_cs;
 
   /**
-   * Planchet containing message to sign and nonce to derive R from
+   * Message to sign.
    */
-  struct TALER_BlindedCsPlanchet planchet;
+  struct GNUNET_CRYPTO_CsBlindedMessage message;
 
 };
 
@@ -188,7 +188,7 @@ struct TALER_CRYPTO_CsRDeriveRequest
   /**
    * Withdraw nonce to derive R from
    */
-  struct TALER_CsNonce nonce;
+  struct GNUNET_CRYPTO_CsSessionNonce nonce;
 };
 
 
@@ -248,14 +248,14 @@ struct TALER_CRYPTO_SignResponse
   struct GNUNET_MessageHeader header;
 
   /**
-   * For now, always zero.
+   * The chosen 'b' (0 or 1).
    */
-  uint32_t reserved;
+  uint32_t b;
 
   /**
-   * Contains the blindided s and the chosen b
+   * Contains the blindided s.
    */
-  struct TALER_BlindedDenominationCsSignAnswer cs_answer;
+  struct GNUNET_CRYPTO_CsBlindS cs_answer;
 };
 
 /**
@@ -274,9 +274,9 @@ struct TALER_CRYPTO_RDeriveResponse
   uint32_t reserved;
 
   /**
-   * derived R
+   * Pair of derived R values
    */
-  struct TALER_DenominationCSPublicRPairP r_pub;
+  struct GNUNET_CRYPTO_CSPublicRPairP r_pub;
 };
 
 
diff --git a/src/util/taler-exchange-secmod-rsa.c 
b/src/util/taler-exchange-secmod-rsa.c
index 414cb4ac..b10e7c63 100644
--- a/src/util/taler-exchange-secmod-rsa.c
+++ b/src/util/taler-exchange-secmod-rsa.c
@@ -409,15 +409,13 @@ generate_response (struct DenominationKey *dk)
  * Do the actual signing work.
  *
  * @param h_rsa key to sign with
- * @param blinded_msg message to sign
- * @param blinded_msg_size number of bytes in @a blinded_msg
+ * @param bm blinded message to sign
  * @param[out] rsa_signaturep set to the RSA signature
  * @return #TALER_EC_NONE on success
  */
 static enum TALER_ErrorCode
 do_sign (const struct TALER_RsaPubHashP *h_rsa,
-         const void *blinded_msg,
-         size_t blinded_msg_size,
+         const struct GNUNET_CRYPTO_RsaBlindedMessage *bm,
          struct GNUNET_CRYPTO_RsaSignature **rsa_signaturep)
 {
   struct DenominationKey *dk;
@@ -447,15 +445,14 @@ do_sign (const struct TALER_RsaPubHashP *h_rsa,
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Received request to sign over %u bytes with key %s\n",
-              (unsigned int) blinded_msg_size,
+              (unsigned int) bm->blinded_msg_size,
               GNUNET_h2s (&h_rsa->hash));
   GNUNET_assert (dk->rc < UINT_MAX);
   dk->rc++;
   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
   rsa_signature
     = GNUNET_CRYPTO_rsa_sign_blinded (dk->denom_priv,
-                                      blinded_msg,
-                                      blinded_msg_size);
+                                      bm);
   GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
   GNUNET_assert (dk->rc > 0);
   dk->rc--;
@@ -548,14 +545,15 @@ static enum GNUNET_GenericReturnValue
 handle_sign_request (struct TES_Client *client,
                      const struct TALER_CRYPTO_SignRequest *sr)
 {
-  const void *blinded_msg = &sr[1];
-  size_t blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr);
+  struct GNUNET_CRYPTO_RsaBlindedMessage bm = {
+    .blinded_msg = (void *) &sr[1],
+    .blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr)
+  };
   struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
   enum TALER_ErrorCode ec;
 
   ec = do_sign (&sr->h_rsa,
-                blinded_msg,
-                blinded_msg_size,
+                &bm,
                 &rsa_signature);
   if (TALER_EC_NONE != ec)
   {
@@ -660,12 +658,13 @@ worker (void *cls)
     {
       struct BatchJob *bj = w->job;
       const struct TALER_CRYPTO_SignRequest *sr = bj->sr;
-      const void *blinded_msg = &sr[1];
-      size_t blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr);
+      struct GNUNET_CRYPTO_RsaBlindedMessage bm = {
+        .blinded_msg = (void *) &sr[1],
+        .blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr)
+      };
 
       bj->ec = do_sign (&sr->h_rsa,
-                        blinded_msg,
-                        blinded_msg_size,
+                        &bm,
                         &bj->rsa_signature);
       sem_up (&bj->sem);
       w->job = NULL;
@@ -880,8 +879,8 @@ setup_key (struct DenominationKey *dk,
   }
   buf_size = GNUNET_CRYPTO_rsa_private_key_encode (priv,
                                                    &buf);
-  TALER_rsa_pub_hash (pub,
-                      &dk->h_rsa);
+  GNUNET_CRYPTO_rsa_public_key_hash (pub,
+                                     &dk->h_rsa.hash);
   GNUNET_asprintf (&dk->filename,
                    "%s/%s/%llu",
                    keydir,
@@ -1545,8 +1544,8 @@ parse_key (struct Denomination *denom,
     dk->denom = denom;
     dk->anchor = anchor;
     dk->filename = GNUNET_strdup (filename);
-    TALER_rsa_pub_hash (pub,
-                        &dk->h_rsa);
+    GNUNET_CRYPTO_rsa_public_key_hash (pub,
+                                       &dk->h_rsa.hash);
     dk->denom_pub = pub;
     generate_response (dk);
     if (GNUNET_OK !=
diff --git a/src/util/test_crypto.c b/src/util/test_crypto.c
index 54f7e794..2a209095 100644
--- a/src/util/test_crypto.c
+++ b/src/util/test_crypto.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2015, 2020-2022 Taler Systems SA
+  (C) 2015, 2020-2023 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -37,14 +37,21 @@ test_high_level (void)
   struct TALER_TransferPublicKeyP trans_pub;
   struct TALER_TransferSecretP secret;
   struct TALER_TransferSecretP secret2;
-  union TALER_DenominationBlindingKeyP bks1;
-  union TALER_DenominationBlindingKeyP bks2;
+  union GNUNET_CRYPTO_BlindingSecretP bks1;
+  union GNUNET_CRYPTO_BlindingSecretP bks2;
   struct TALER_CoinSpendPrivateKeyP coin_priv1;
   struct TALER_CoinSpendPrivateKeyP coin_priv2;
   struct TALER_PlanchetMasterSecretP ps1;
   struct TALER_PlanchetMasterSecretP ps2;
-  struct TALER_ExchangeWithdrawValues alg1;
-  struct TALER_ExchangeWithdrawValues alg2;
+  struct GNUNET_CRYPTO_BlindingInputValues bi = {
+    .cipher = GNUNET_CRYPTO_BSA_RSA
+  };
+  struct TALER_ExchangeWithdrawValues alg1 = {
+    .blinding_inputs = &bi
+  };
+  struct TALER_ExchangeWithdrawValues alg2 = {
+    .blinding_inputs = &bi
+  };
 
   GNUNET_CRYPTO_eddsa_key_create (&coin_priv.eddsa_priv);
   GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv.eddsa_priv,
@@ -70,14 +77,12 @@ test_high_level (void)
   TALER_transfer_secret_to_planchet_secret (&secret,
                                             0,
                                             &ps1);
-  alg1.cipher = TALER_DENOMINATION_RSA;
   TALER_planchet_setup_coin_priv (&ps1,
                                   &alg1,
                                   &coin_priv1);
   TALER_planchet_blinding_secret_create (&ps1,
                                          &alg1,
                                          &bks1);
-  alg2.cipher = TALER_DENOMINATION_RSA;
   TALER_transfer_secret_to_planchet_secret (&secret,
                                             1,
                                             &ps2);
@@ -116,10 +121,10 @@ test_planchets_rsa (uint8_t age)
 {
   struct TALER_PlanchetMasterSecretP ps;
   struct TALER_CoinSpendPrivateKeyP coin_priv;
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
   struct TALER_DenominationPrivateKey dk_priv;
   struct TALER_DenominationPublicKey dk_pub;
-  struct TALER_ExchangeWithdrawValues alg_values;
+  const struct TALER_ExchangeWithdrawValues *alg_values;
   struct TALER_PlanchetDetail pd;
   struct TALER_BlindedDenominationSignature blind_sig;
   struct TALER_FreshCoin coin;
@@ -127,6 +132,7 @@ test_planchets_rsa (uint8_t age)
   struct TALER_AgeCommitmentHash *ach = NULL;
   struct TALER_AgeCommitmentHash ah = {0};
 
+  alg_values = TALER_denom_ewv_rsa_singleton ();
   if (0 < age)
   {
     struct TALER_AgeCommitmentProof acp;
@@ -152,7 +158,7 @@ test_planchets_rsa (uint8_t age)
   GNUNET_assert (GNUNET_SYSERR ==
                  TALER_denom_priv_create (&dk_priv,
                                           &dk_pub,
-                                          TALER_DENOMINATION_INVALID));
+                                          GNUNET_CRYPTO_BSA_INVALID));
   GNUNET_log_skip (1, GNUNET_YES);
   GNUNET_assert (GNUNET_SYSERR ==
                  TALER_denom_priv_create (&dk_priv,
@@ -162,19 +168,19 @@ test_planchets_rsa (uint8_t age)
   GNUNET_assert (GNUNET_OK ==
                  TALER_denom_priv_create (&dk_priv,
                                           &dk_pub,
-                                          TALER_DENOMINATION_RSA,
+                                          GNUNET_CRYPTO_BSA_RSA,
                                           1024));
-  alg_values.cipher = TALER_DENOMINATION_RSA;
   TALER_planchet_setup_coin_priv (&ps,
-                                  &alg_values,
+                                  alg_values,
                                   &coin_priv);
   TALER_planchet_blinding_secret_create (&ps,
-                                         &alg_values,
+                                         alg_values,
                                          &bks);
   GNUNET_assert (GNUNET_OK ==
                  TALER_planchet_prepare (&dk_pub,
-                                         &alg_values,
+                                         alg_values,
                                          &bks,
+                                         NULL,
                                          &coin_priv,
                                          ach,
                                          &c_hash,
@@ -192,7 +198,7 @@ test_planchets_rsa (uint8_t age)
                                          &coin_priv,
                                          ach,
                                          &c_hash,
-                                         &alg_values,
+                                         alg_values,
                                          &coin));
   TALER_blinded_denom_sig_free (&blind_sig);
   TALER_denom_sig_free (&coin.sig);
@@ -202,39 +208,6 @@ test_planchets_rsa (uint8_t age)
 }
 
 
-/**
- * @brief Function for CS signatures to derive public R_0 and R_1
- *
- * @param nonce withdraw nonce from a client
- * @param denom_priv denomination privkey as long-term secret
- * @param r_pub the resulting R_0 and R_1
- * @return enum GNUNET_GenericReturnValue
- */
-static enum GNUNET_GenericReturnValue
-derive_r_public (
-  const struct TALER_CsNonce *nonce,
-  const struct TALER_DenominationPrivateKey *denom_priv,
-  struct TALER_DenominationCSPublicRPairP *r_pub)
-{
-  struct GNUNET_CRYPTO_CsRSecret r[2];
-
-  if (denom_priv->cipher != TALER_DENOMINATION_CS)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_CRYPTO_cs_r_derive (&nonce->nonce,
-                             "rw",
-                             &denom_priv->details.cs_private_key,
-                             r);
-  GNUNET_CRYPTO_cs_r_get_public (&r[0],
-                                 &r_pub->r_pub[0]);
-  GNUNET_CRYPTO_cs_r_get_public (&r[1],
-                                 &r_pub->r_pub[1]);
-  return GNUNET_OK;
-}
-
-
 /**
  * Test the basic planchet functionality of creating a fresh planchet with CS 
denomination
  * and extracting the respective signature.
@@ -246,11 +219,12 @@ test_planchets_cs (uint8_t age)
 {
   struct TALER_PlanchetMasterSecretP ps;
   struct TALER_CoinSpendPrivateKeyP coin_priv;
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
   struct TALER_DenominationPrivateKey dk_priv;
   struct TALER_DenominationPublicKey dk_pub;
   struct TALER_PlanchetDetail pd;
   struct TALER_CoinPubHashP c_hash;
+  union GNUNET_CRYPTO_BlindSessionNonce nonce;
   struct TALER_BlindedDenominationSignature blind_sig;
   struct TALER_FreshCoin coin;
   struct TALER_ExchangeWithdrawValues alg_values;
@@ -281,16 +255,17 @@ test_planchets_cs (uint8_t age)
   GNUNET_assert (GNUNET_OK ==
                  TALER_denom_priv_create (&dk_priv,
                                           &dk_pub,
-                                          TALER_DENOMINATION_CS));
-  alg_values.cipher = TALER_DENOMINATION_CS;
+                                          GNUNET_CRYPTO_BSA_CS));
   TALER_cs_withdraw_nonce_derive (
     &ps,
-    &pd.blinded_planchet.details.cs_blinded_planchet.nonce);
-  GNUNET_assert (GNUNET_OK ==
-                 derive_r_public (
-                   &pd.blinded_planchet.details.cs_blinded_planchet.nonce,
-                   &dk_priv,
-                   &alg_values.details.cs_values));
+    &nonce.cs_nonce);
+  // FIXME: define Taler abstraction for this:
+  alg_values.blinding_inputs
+    = GNUNET_CRYPTO_get_blinding_input_values (dk_priv.bsign_priv_key,
+                                               &nonce,
+                                               "rw");
+  TALER_denom_pub_hash (&dk_pub,
+                        &pd.denom_pub_hash);
   TALER_planchet_setup_coin_priv (&ps,
                                   &alg_values,
                                   &coin_priv);
@@ -301,6 +276,7 @@ test_planchets_cs (uint8_t age)
                  TALER_planchet_prepare (&dk_pub,
                                          &alg_values,
                                          &bks,
+                                         &nonce,
                                          &coin_priv,
                                          ach,
                                          &c_hash,
@@ -310,7 +286,6 @@ test_planchets_cs (uint8_t age)
                                            &dk_priv,
                                            false,
                                            &pd.blinded_planchet));
-  TALER_planchet_detail_free (&pd);
   GNUNET_assert (GNUNET_OK ==
                  TALER_planchet_to_coin (&dk_pub,
                                          &blind_sig,
diff --git a/src/util/test_helper_cs.c b/src/util/test_helper_cs.c
index 2dada0e1..8a60ee2f 100644
--- a/src/util/test_helper_cs.c
+++ b/src/util/test_helper_cs.c
@@ -129,7 +129,7 @@ free_keys (void)
  * @param validity_duration how long does the key remain available for signing;
  *                 zero if the key has been revoked or purged
  * @param h_cs hash of the @a denom_pub that is available (or was purged)
- * @param denom_pub the public key itself, NULL if the key was revoked or 
purged
+ * @param bs_pub the public key itself, NULL if the key was revoked or purged
  * @param sm_pub public key of the security module, NULL if the key was 
revoked or purged
  * @param sm_sig signature from the security module, NULL if the key was 
revoked or purged
  *               The signature was already verified against @a sm_pub.
@@ -140,7 +140,7 @@ key_cb (void *cls,
         struct GNUNET_TIME_Timestamp start_time,
         struct GNUNET_TIME_Relative validity_duration,
         const struct TALER_CsPubHashP *h_cs,
-        const struct TALER_DenominationPublicKey *denom_pub,
+        struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub,
         const struct TALER_SecurityModulePublicKeyP *sm_pub,
         const struct TALER_SecurityModuleSignatureP *sm_sig)
 {
@@ -155,7 +155,7 @@ key_cb (void *cls,
   {
     bool found = false;
 
-    GNUNET_break (NULL == denom_pub);
+    GNUNET_break (NULL == bs_pub);
     GNUNET_break (NULL == section_name);
     for (unsigned int i = 0; i<MAX_KEYS; i++)
       if (0 == GNUNET_memcmp (h_cs,
@@ -176,7 +176,7 @@ key_cb (void *cls,
     return;
   }
 
-  GNUNET_break (NULL != denom_pub);
+  GNUNET_break (NULL != bs_pub);
   for (unsigned int i = 0; i<MAX_KEYS; i++)
     if (! keys[i].valid)
     {
@@ -184,8 +184,8 @@ key_cb (void *cls,
       keys[i].h_cs = *h_cs;
       keys[i].start_time = start_time;
       keys[i].validity_duration = validity_duration;
-      TALER_denom_pub_deep_copy (&keys[i].denom_pub,
-                                 denom_pub);
+      keys[i].denom_pub.bsign_pub_key
+        = GNUNET_CRYPTO_bsign_pub_incref (bs_pub);
       num_keys++;
       return;
     }
@@ -268,9 +268,15 @@ test_r_derive (struct TALER_CRYPTO_CsDenominationHelper 
*dh)
   bool success = false;
   struct TALER_PlanchetMasterSecretP ps;
   struct TALER_CoinSpendPrivateKeyP coin_priv;
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
   struct TALER_CoinPubHashP c_hash;
-  struct TALER_ExchangeWithdrawValues alg_values;
+  struct GNUNET_CRYPTO_BlindingInputValues bi = {
+    .cipher = GNUNET_CRYPTO_BSA_CS
+  };
+  struct TALER_ExchangeWithdrawValues alg_values = {
+    .blinding_inputs = &bi
+  };
+  union GNUNET_CRYPTO_BlindSessionNonce nonce;
 
   TALER_planchet_master_setup_random (&ps);
   for (unsigned int i = 0; i<MAX_KEYS; i++)
@@ -279,27 +285,25 @@ test_r_derive (struct TALER_CRYPTO_CsDenominationHelper 
*dh)
 
     if (! keys[i].valid)
       continue;
-    GNUNET_assert (TALER_DENOMINATION_CS ==
-                   keys[i].denom_pub.cipher);
-    pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
+    GNUNET_assert (GNUNET_CRYPTO_BSA_CS ==
+                   keys[i].denom_pub.bsign_pub_key->cipher);
     TALER_cs_withdraw_nonce_derive (
       &ps,
-      &pd.blinded_planchet.details.cs_blinded_planchet.nonce);
+      &nonce.cs_nonce);
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Requesting R derivation with key %s\n",
                 GNUNET_h2s (&keys[i].h_cs.hash));
-    alg_values.cipher = TALER_DENOMINATION_CS;
     {
       struct TALER_CRYPTO_CsDeriveRequest cdr = {
         .h_cs = &keys[i].h_cs,
-        .nonce = &pd.blinded_planchet.details.cs_blinded_planchet.nonce
+        .nonce = &nonce.cs_nonce
       };
 
       ec = TALER_CRYPTO_helper_cs_r_derive (
         dh,
         &cdr,
         false,
-        &alg_values.details.cs_values);
+        &bi.details.cs_values);
     }
     switch (ec)
     {
@@ -336,6 +340,7 @@ test_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh)
                      TALER_planchet_prepare (&keys[i].denom_pub,
                                              &alg_values,
                                              &bks,
+                                             &nonce,
                                              &coin_priv,
                                              NULL, /* no age commitment */
                                              &c_hash,
@@ -379,11 +384,10 @@ test_r_derive (struct TALER_CRYPTO_CsDenominationHelper 
*dh)
   /* check R derivation does not work if the key is unknown */
   {
     struct TALER_CsPubHashP rnd;
-    struct TALER_CsNonce nonce;
-    struct TALER_DenominationCSPublicRPairP crp;
+    struct GNUNET_CRYPTO_CSPublicRPairP crp;
     struct TALER_CRYPTO_CsDeriveRequest cdr = {
       .h_cs = &rnd,
-      .nonce = &nonce,
+      .nonce = &nonce.cs_nonce,
     };
 
     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
@@ -423,9 +427,15 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper *dh)
   bool success = false;
   struct TALER_PlanchetMasterSecretP ps;
   struct TALER_CoinSpendPrivateKeyP coin_priv;
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
   struct TALER_CoinPubHashP c_hash;
-  struct TALER_ExchangeWithdrawValues alg_values;
+  struct GNUNET_CRYPTO_BlindingInputValues bi = {
+    .cipher = GNUNET_CRYPTO_BSA_CS
+  };
+  struct TALER_ExchangeWithdrawValues alg_values = {
+    .blinding_inputs = &bi
+  };
+  union GNUNET_CRYPTO_BlindSessionNonce nonce;
 
   TALER_planchet_master_setup_random (&ps);
   for (unsigned int i = 0; i<MAX_KEYS; i++)
@@ -437,19 +447,16 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper 
*dh)
       struct TALER_CRYPTO_CsSignRequest csr;
       struct TALER_CRYPTO_CsDeriveRequest cdr = {
         .h_cs = &keys[i].h_cs,
-        .nonce = &pd.blinded_planchet.details.cs_blinded_planchet.nonce
+        .nonce = &nonce.cs_nonce
       };
 
-      pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
       TALER_cs_withdraw_nonce_derive (&ps,
-                                      &pd.blinded_planchet.details.
-                                      cs_blinded_planchet.nonce);
-      alg_values.cipher = TALER_DENOMINATION_CS;
+                                      &nonce.cs_nonce);
       ec = TALER_CRYPTO_helper_cs_r_derive (
         dh,
         &cdr,
         false,
-        &alg_values.details.cs_values);
+        &bi.details.cs_values);
       if (TALER_EC_NONE != ec)
         continue;
       TALER_planchet_setup_coin_priv (&ps,
@@ -458,11 +465,11 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper 
*dh)
       TALER_planchet_blinding_secret_create (&ps,
                                              &alg_values,
                                              &bks);
-
       GNUNET_assert (GNUNET_YES ==
                      TALER_planchet_prepare (&keys[i].denom_pub,
                                              &alg_values,
                                              &bks,
+                                             &nonce,
                                              &coin_priv,
                                              NULL, /* no age commitment */
                                              &c_hash,
@@ -472,7 +479,7 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper *dh)
                   GNUNET_h2s (&keys[i].h_cs.hash));
       csr.h_cs = &keys[i].h_cs;
       csr.blinded_planchet
-        = &pd.blinded_planchet.details.cs_blinded_planchet;
+        = &pd.blinded_planchet.blinded_message->details.cs_blinded_message;
       ec = TALER_CRYPTO_helper_cs_sign (
         dh,
         &csr,
@@ -563,18 +570,18 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper 
*dh)
     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
                                 &rnd,
                                 sizeof (rnd));
-    pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
     GNUNET_assert (GNUNET_YES ==
                    TALER_planchet_prepare (&keys[0].denom_pub,
                                            &alg_values,
                                            &bks,
+                                           &nonce,
                                            &coin_priv,
                                            NULL, /* no age commitment */
                                            &c_hash,
                                            &pd));
     csr.h_cs = &rnd;
     csr.blinded_planchet
-      = &pd.blinded_planchet.details.cs_blinded_planchet;
+      = &pd.blinded_planchet.blinded_message->details.cs_blinded_message;
     ec = TALER_CRYPTO_helper_cs_sign (
       dh,
       &csr,
@@ -613,9 +620,11 @@ test_batch_signing (struct 
TALER_CRYPTO_CsDenominationHelper *dh,
   bool success = false;
   struct TALER_PlanchetMasterSecretP ps[batch_size];
   struct TALER_CoinSpendPrivateKeyP coin_priv[batch_size];
-  union TALER_DenominationBlindingKeyP bks[batch_size];
+  union GNUNET_CRYPTO_BlindingSecretP bks[batch_size];
   struct TALER_CoinPubHashP c_hash[batch_size];
+  struct GNUNET_CRYPTO_BlindingInputValues bi[batch_size];
   struct TALER_ExchangeWithdrawValues alg_values[batch_size];
+  union GNUNET_CRYPTO_BlindSessionNonce nonces[batch_size];
 
   for (unsigned int i = 0; i<batch_size; i++)
     TALER_planchet_master_setup_random (&ps[i]);
@@ -627,30 +636,29 @@ test_batch_signing (struct 
TALER_CRYPTO_CsDenominationHelper *dh,
       struct TALER_PlanchetDetail pd[batch_size];
       struct TALER_CRYPTO_CsSignRequest csr[batch_size];
       struct TALER_CRYPTO_CsDeriveRequest cdr[batch_size];
-      struct TALER_DenominationCSPublicRPairP crps[batch_size];
+      struct GNUNET_CRYPTO_CSPublicRPairP crps[batch_size];
 
       for (unsigned int i = 0; i<batch_size; i++)
       {
         cdr[i].h_cs = &keys[k].h_cs;
-        cdr[i].nonce =
-          &pd[i].blinded_planchet.details.cs_blinded_planchet.nonce;
-        pd[i].blinded_planchet.cipher = TALER_DENOMINATION_CS;
+        cdr[i].nonce = &nonces[i].cs_nonce;
         TALER_cs_withdraw_nonce_derive (
           &ps[i],
-          &pd[i].blinded_planchet.details.cs_blinded_planchet.nonce);
-        alg_values[i].cipher = TALER_DENOMINATION_CS;
+          &nonces[i].cs_nonce);
+        bi[i].cipher = GNUNET_CRYPTO_BSA_CS;
+        alg_values[i].blinding_inputs = &bi[i];
       }
       ec = TALER_CRYPTO_helper_cs_r_batch_derive (
         dh,
-        cdr,
         batch_size,
+        cdr,
         false,
         crps);
       if (TALER_EC_NONE != ec)
         continue;
       for (unsigned int i = 0; i<batch_size; i++)
       {
-        alg_values[i].details.cs_values = crps[i];
+        bi[i].details.cs_values = crps[i];
         TALER_planchet_setup_coin_priv (&ps[i],
                                         &alg_values[i],
                                         &coin_priv[i]);
@@ -661,6 +669,7 @@ test_batch_signing (struct 
TALER_CRYPTO_CsDenominationHelper *dh,
                        TALER_planchet_prepare (&keys[k].denom_pub,
                                                &alg_values[i],
                                                &bks[i],
+                                               &nonces[i],
                                                &coin_priv[i],
                                                NULL, /* no age commitment */
                                                &c_hash[i],
@@ -670,12 +679,12 @@ test_batch_signing (struct 
TALER_CRYPTO_CsDenominationHelper *dh,
                     GNUNET_h2s (&keys[k].h_cs.hash));
         csr[i].h_cs = &keys[k].h_cs;
         csr[i].blinded_planchet
-          = &pd[i].blinded_planchet.details.cs_blinded_planchet;
+          = 
&pd[i].blinded_planchet.blinded_message->details.cs_blinded_message;
       }
       ec = TALER_CRYPTO_helper_cs_batch_sign (
         dh,
-        csr,
         batch_size,
+        csr,
         false,
         ds);
     }
@@ -768,22 +777,22 @@ test_batch_signing (struct 
TALER_CRYPTO_CsDenominationHelper *dh,
     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
                                 &rnd,
                                 sizeof (rnd));
-    pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
     GNUNET_assert (GNUNET_YES ==
                    TALER_planchet_prepare (&keys[0].denom_pub,
                                            &alg_values[0],
                                            &bks[0],
+                                           &nonces[0],
                                            &coin_priv[0],
                                            NULL, /* no age commitment */
                                            &c_hash[0],
                                            &pd));
     csr.h_cs = &rnd;
     csr.blinded_planchet
-      = &pd.blinded_planchet.details.cs_blinded_planchet;
+      = &pd.blinded_planchet.blinded_message->details.cs_blinded_message;
     ec = TALER_CRYPTO_helper_cs_batch_sign (
       dh,
-      &csr,
       1,
+      &csr,
       false,
       &ds[0]);
     if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
@@ -816,8 +825,13 @@ perf_signing (struct TALER_CRYPTO_CsDenominationHelper *dh,
   struct GNUNET_TIME_Relative duration;
   struct TALER_PlanchetMasterSecretP ps;
   struct TALER_CoinSpendPrivateKeyP coin_priv;
-  union TALER_DenominationBlindingKeyP bks;
-  struct TALER_ExchangeWithdrawValues alg_values;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
+  struct GNUNET_CRYPTO_BlindingInputValues bv = {
+    .cipher = GNUNET_CRYPTO_BSA_CS
+  };
+  struct TALER_ExchangeWithdrawValues alg_values = {
+    .blinding_inputs = &bv
+  };
 
   TALER_planchet_master_setup_random (&ps);
   duration = GNUNET_TIME_UNIT_ZERO;
@@ -841,21 +855,20 @@ perf_signing (struct TALER_CRYPTO_CsDenominationHelper 
*dh,
       {
         struct TALER_CoinPubHashP c_hash;
         struct TALER_PlanchetDetail pd;
+        union GNUNET_CRYPTO_BlindSessionNonce nonce;
         struct TALER_CRYPTO_CsDeriveRequest cdr = {
           .h_cs = &keys[i].h_cs,
-          .nonce = &pd.blinded_planchet.details.cs_blinded_planchet.nonce
+          .nonce = &nonce.cs_nonce
         };
 
-        pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
-        TALER_cs_withdraw_nonce_derive (&ps,
-                                        &pd.blinded_planchet.details.
-                                        cs_blinded_planchet.nonce);
-        alg_values.cipher = TALER_DENOMINATION_CS;
+        TALER_cs_withdraw_nonce_derive (
+          &ps,
+          &nonce.cs_nonce);
         ec = TALER_CRYPTO_helper_cs_r_derive (
           dh,
           &cdr,
           true,
-          &alg_values.details.cs_values);
+          &bv.details.cs_values);
         if (TALER_EC_NONE != ec)
           continue;
         TALER_planchet_setup_coin_priv (&ps,
@@ -868,6 +881,7 @@ perf_signing (struct TALER_CRYPTO_CsDenominationHelper *dh,
                        TALER_planchet_prepare (&keys[i].denom_pub,
                                                &alg_values,
                                                &bks,
+                                               &nonce,
                                                &coin_priv,
                                                NULL, /* no age commitment */
                                                &c_hash,
@@ -881,7 +895,7 @@ perf_signing (struct TALER_CRYPTO_CsDenominationHelper *dh,
 
           csr.h_cs = &keys[i].h_cs;
           csr.blinded_planchet
-            = &pd.blinded_planchet.details.cs_blinded_planchet;
+            = &pd.blinded_planchet.blinded_message->details.cs_blinded_message;
           ec = TALER_CRYPTO_helper_cs_sign (
             dh,
             &csr,
diff --git a/src/util/test_helper_rsa.c b/src/util/test_helper_rsa.c
index 1c7cc5bf..1189e0cc 100644
--- a/src/util/test_helper_rsa.c
+++ b/src/util/test_helper_rsa.c
@@ -129,7 +129,7 @@ free_keys (void)
  * @param validity_duration how long does the key remain available for signing;
  *                 zero if the key has been revoked or purged
  * @param h_rsa hash of the @a denom_pub that is available (or was purged)
- * @param denom_pub the public key itself, NULL if the key was revoked or 
purged
+ * @param bs_pub the public key itself, NULL if the key was revoked or purged
  * @param sm_pub public key of the security module, NULL if the key was 
revoked or purged
  * @param sm_sig signature from the security module, NULL if the key was 
revoked or purged
  *               The signature was already verified against @a sm_pub.
@@ -140,7 +140,7 @@ key_cb (void *cls,
         struct GNUNET_TIME_Timestamp start_time,
         struct GNUNET_TIME_Relative validity_duration,
         const struct TALER_RsaPubHashP *h_rsa,
-        const struct TALER_DenominationPublicKey *denom_pub,
+        struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub,
         const struct TALER_SecurityModulePublicKeyP *sm_pub,
         const struct TALER_SecurityModuleSignatureP *sm_sig)
 {
@@ -155,7 +155,7 @@ key_cb (void *cls,
   {
     bool found = false;
 
-    GNUNET_break (NULL == denom_pub);
+    GNUNET_break (NULL == bs_pub);
     GNUNET_break (NULL == section_name);
     for (unsigned int i = 0; i<MAX_KEYS; i++)
       if (0 == GNUNET_memcmp (h_rsa,
@@ -176,7 +176,7 @@ key_cb (void *cls,
     return;
   }
 
-  GNUNET_break (NULL != denom_pub);
+  GNUNET_break (NULL != bs_pub);
   for (unsigned int i = 0; i<MAX_KEYS; i++)
     if (! keys[i].valid)
     {
@@ -184,8 +184,8 @@ key_cb (void *cls,
       keys[i].h_rsa = *h_rsa;
       keys[i].start_time = start_time;
       keys[i].validity_duration = validity_duration;
-      TALER_denom_pub_deep_copy (&keys[i].denom_pub,
-                                 denom_pub);
+      keys[i].denom_pub.bsign_pub_key
+        = GNUNET_CRYPTO_bsign_pub_incref (bs_pub);
       num_keys++;
       return;
     }
@@ -268,19 +268,22 @@ test_signing (struct TALER_CRYPTO_RsaDenominationHelper 
*dh)
   enum TALER_ErrorCode ec;
   bool success = false;
   struct TALER_PlanchetMasterSecretP ps;
-  struct TALER_ExchangeWithdrawValues alg_values;
+  const struct TALER_ExchangeWithdrawValues *alg_values
+    = TALER_denom_ewv_rsa_singleton ();
   struct TALER_AgeCommitmentHash ach;
   struct TALER_CoinPubHashP c_hash;
   struct TALER_CoinSpendPrivateKeyP coin_priv;
-  union TALER_DenominationBlindingKeyP bks;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
 
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
                               &ps,
                               sizeof (ps));
-
-  alg_values.cipher = TALER_DENOMINATION_RSA;
-  TALER_planchet_setup_coin_priv (&ps, &alg_values, &coin_priv);
-  TALER_planchet_blinding_secret_create (&ps, &alg_values, &bks);
+  TALER_planchet_setup_coin_priv (&ps,
+                                  alg_values,
+                                  &coin_priv);
+  TALER_planchet_blinding_secret_create (&ps,
+                                         alg_values,
+                                         &bks);
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
                               &ach,
                               sizeof(ach));
@@ -289,17 +292,17 @@ test_signing (struct TALER_CRYPTO_RsaDenominationHelper 
*dh)
   {
     if (! keys[i].valid)
       continue;
-    if (TALER_DENOMINATION_RSA != keys[i].denom_pub.cipher)
+    if (GNUNET_CRYPTO_BSA_RSA !=
+        keys[i].denom_pub.bsign_pub_key->cipher)
       continue;
     {
-      struct TALER_PlanchetDetail pd = {
-        .blinded_planchet.cipher = TALER_DENOMINATION_RSA
-      };
+      struct TALER_PlanchetDetail pd;
 
       GNUNET_assert (GNUNET_YES ==
                      TALER_planchet_prepare (&keys[i].denom_pub,
-                                             &alg_values,
+                                             alg_values,
                                              &bks,
+                                             NULL,
                                              &coin_priv,
                                              &ach,
                                              &c_hash,
@@ -308,9 +311,11 @@ test_signing (struct TALER_CRYPTO_RsaDenominationHelper 
*dh)
         struct TALER_CRYPTO_RsaSignRequest rsr = {
           .h_rsa = &keys[i].h_rsa,
           .msg =
-            pd.blinded_planchet.details.rsa_blinded_planchet.blinded_msg,
+            pd.blinded_planchet.blinded_message->details.rsa_blinded_message.
+            blinded_msg,
           .msg_size =
-            pd.blinded_planchet.details.rsa_blinded_planchet.blinded_msg_size
+            pd.blinded_planchet.blinded_message->details.rsa_blinded_message.
+            blinded_msg_size
         };
 
         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -352,7 +357,7 @@ test_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh)
                                      &ds,
                                      &bks,
                                      &c_hash,
-                                     &alg_values,
+                                     alg_values,
                                      &keys[i].denom_pub))
         {
           GNUNET_break (0);
@@ -457,11 +462,11 @@ test_batch_signing (struct 
TALER_CRYPTO_RsaDenominationHelper *dh,
   enum TALER_ErrorCode ec;
   bool success = false;
   struct TALER_PlanchetMasterSecretP ps[batch_size];
-  struct TALER_ExchangeWithdrawValues alg_values[batch_size];
+  const struct TALER_ExchangeWithdrawValues *alg_values;
   struct TALER_AgeCommitmentHash ach[batch_size];
   struct TALER_CoinPubHashP c_hash[batch_size];
   struct TALER_CoinSpendPrivateKeyP coin_priv[batch_size];
-  union TALER_DenominationBlindingKeyP bks[batch_size];
+  union GNUNET_CRYPTO_BlindingSecretP bks[batch_size];
 
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
                               &ps,
@@ -469,14 +474,14 @@ test_batch_signing (struct 
TALER_CRYPTO_RsaDenominationHelper *dh,
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
                               &ach,
                               sizeof(ach));
+  alg_values = TALER_denom_ewv_rsa_singleton ();
   for (unsigned int i = 0; i<batch_size; i++)
   {
-    alg_values[i].cipher = TALER_DENOMINATION_RSA;
     TALER_planchet_setup_coin_priv (&ps[i],
-                                    &alg_values[i],
+                                    alg_values,
                                     &coin_priv[i]);
     TALER_planchet_blinding_secret_create (&ps[i],
-                                           &alg_values[i],
+                                           alg_values,
                                            &bks[i]);
   }
   for (unsigned int k = 0; k<MAX_KEYS; k++)
@@ -485,7 +490,8 @@ test_batch_signing (struct 
TALER_CRYPTO_RsaDenominationHelper *dh,
       break; /* only do one round */
     if (! keys[k].valid)
       continue;
-    if (TALER_DENOMINATION_RSA != keys[k].denom_pub.cipher)
+    if (GNUNET_CRYPTO_BSA_RSA !=
+        keys[k].denom_pub.bsign_pub_key->cipher)
       continue;
     {
       struct TALER_PlanchetDetail pd[batch_size];
@@ -493,11 +499,13 @@ test_batch_signing (struct 
TALER_CRYPTO_RsaDenominationHelper *dh,
 
       for (unsigned int i = 0; i<batch_size; i++)
       {
-        pd[i].blinded_planchet.cipher = TALER_DENOMINATION_RSA;
+        pd[i].blinded_planchet.blinded_message->cipher
+          = GNUNET_CRYPTO_BSA_RSA;
         GNUNET_assert (GNUNET_YES ==
                        TALER_planchet_prepare (&keys[k].denom_pub,
-                                               &alg_values[i],
+                                               alg_values,
                                                &bks[i],
+                                               NULL,
                                                &coin_priv[i],
                                                &ach[i],
                                                &c_hash[i],
@@ -505,19 +513,21 @@ test_batch_signing (struct 
TALER_CRYPTO_RsaDenominationHelper *dh,
         rsr[i].h_rsa
           = &keys[k].h_rsa;
         rsr[i].msg
-          = pd[i].blinded_planchet.details.rsa_blinded_planchet.blinded_msg;
+          = 
pd[i].blinded_planchet.blinded_message->details.rsa_blinded_message.
+            blinded_msg;
         rsr[i].msg_size
-          = 
pd[i].blinded_planchet.details.rsa_blinded_planchet.blinded_msg_size;
+          = 
pd[i].blinded_planchet.blinded_message->details.rsa_blinded_message.
+            blinded_msg_size;
       }
       ec = TALER_CRYPTO_helper_rsa_batch_sign (dh,
-                                               rsr,
                                                batch_size,
+                                               rsr,
                                                ds);
       for (unsigned int i = 0; i<batch_size; i++)
       {
         if (TALER_EC_NONE == ec)
-          GNUNET_break (TALER_DENOMINATION_RSA ==
-                        ds[i].cipher);
+          GNUNET_break (GNUNET_CRYPTO_BSA_RSA ==
+                        ds[i].blinded_sig->cipher);
         TALER_blinded_planchet_free (&pd[i].blinded_planchet);
       }
     }
@@ -553,7 +563,7 @@ test_batch_signing (struct 
TALER_CRYPTO_RsaDenominationHelper *dh,
                                        &ds[i],
                                        &bks[i],
                                        &c_hash[i],
-                                       &alg_values[i],
+                                       alg_values,
                                        &keys[k].denom_pub))
           {
             GNUNET_break (0);
@@ -637,8 +647,8 @@ test_batch_signing (struct 
TALER_CRYPTO_RsaDenominationHelper *dh,
                                 &rnd,
                                 sizeof (rnd));
     ec = TALER_CRYPTO_helper_rsa_batch_sign (dh,
-                                             &rsr,
                                              1,
+                                             &rsr,
                                              ds);
     if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
     {
@@ -674,13 +684,17 @@ perf_signing (struct TALER_CRYPTO_RsaDenominationHelper 
*dh,
   struct TALER_PlanchetMasterSecretP ps;
   struct TALER_CoinSpendPrivateKeyP coin_priv;
   struct TALER_AgeCommitmentHash ach;
-  union TALER_DenominationBlindingKeyP bks;
-  struct TALER_ExchangeWithdrawValues alg_values;
+  union GNUNET_CRYPTO_BlindingSecretP bks;
+  const struct TALER_ExchangeWithdrawValues *alg_values
+    = TALER_denom_ewv_rsa_singleton ();
 
   TALER_planchet_master_setup_random (&ps);
-  alg_values.cipher = TALER_DENOMINATION_RSA;
-  TALER_planchet_setup_coin_priv (&ps, &alg_values, &coin_priv);
-  TALER_planchet_blinding_secret_create (&ps, &alg_values, &bks);
+  TALER_planchet_setup_coin_priv (&ps,
+                                  alg_values,
+                                  &coin_priv);
+  TALER_planchet_blinding_secret_create (&ps,
+                                         alg_values,
+                                         &bks);
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
                               &ach,
                               sizeof(ach));
@@ -692,7 +706,8 @@ perf_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh,
     {
       if (! keys[i].valid)
         continue;
-      if (TALER_DENOMINATION_RSA != keys[i].denom_pub.cipher)
+      if (GNUNET_CRYPTO_BSA_RSA !=
+          keys[i].denom_pub.bsign_pub_key->cipher)
         continue;
       if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
                                       keys[i].start_time.abs_time),
@@ -710,8 +725,9 @@ perf_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh,
 
         GNUNET_assert (GNUNET_YES ==
                        TALER_planchet_prepare (&keys[i].denom_pub,
-                                               &alg_values,
+                                               alg_values,
                                                &bks,
+                                               NULL,
                                                &coin_priv,
                                                &ach,
                                                &c_hash,
@@ -724,9 +740,11 @@ perf_signing (struct TALER_CRYPTO_RsaDenominationHelper 
*dh,
           struct TALER_CRYPTO_RsaSignRequest rsr = {
             .h_rsa = &keys[i].h_rsa,
             .msg =
-              pd.blinded_planchet.details.rsa_blinded_planchet.blinded_msg,
+              pd.blinded_planchet.blinded_message->details.rsa_blinded_message.
+              blinded_msg,
             .msg_size =
-              pd.blinded_planchet.details.rsa_blinded_planchet.blinded_msg_size
+              pd.blinded_planchet.blinded_message->details.rsa_blinded_message.
+              blinded_msg_size
           };
 
           ec = TALER_CRYPTO_helper_rsa_sign (dh,
diff --git a/src/util/wallet_signatures.c b/src/util/wallet_signatures.c
index e44635dd..0b6ab543 100644
--- a/src/util/wallet_signatures.c
+++ b/src/util/wallet_signatures.c
@@ -320,7 +320,7 @@ struct TALER_RecoupRequestPS
   /**
    * Blinding factor that was used to withdraw the coin.
    */
-  union TALER_DenominationBlindingKeyP coin_blind;
+  union GNUNET_CRYPTO_BlindingSecretP coin_blind;
 
 };
 
@@ -330,7 +330,7 @@ GNUNET_NETWORK_STRUCT_END
 enum GNUNET_GenericReturnValue
 TALER_wallet_recoup_verify (
   const struct TALER_DenominationHashP *h_denom_pub,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   const struct TALER_CoinSpendSignatureP *coin_sig)
 {
@@ -351,7 +351,7 @@ TALER_wallet_recoup_verify (
 void
 TALER_wallet_recoup_sign (
   const struct TALER_DenominationHashP *h_denom_pub,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   struct TALER_CoinSpendSignatureP *coin_sig)
 {
@@ -371,7 +371,7 @@ TALER_wallet_recoup_sign (
 enum GNUNET_GenericReturnValue
 TALER_wallet_recoup_refresh_verify (
   const struct TALER_DenominationHashP *h_denom_pub,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   const struct TALER_CoinSpendSignatureP *coin_sig)
 {
@@ -392,7 +392,7 @@ TALER_wallet_recoup_refresh_verify (
 void
 TALER_wallet_recoup_refresh_sign (
   const struct TALER_DenominationHashP *h_denom_pub,
-  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   struct TALER_CoinSpendSignatureP *coin_sig)
 {

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]