github.com/adecaro/fabric-ca@v2.0.0-alpha+incompatible/lib/server/idemix/issuer_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package idemix_test
     8  
     9  import (
    10  	"crypto/ecdsa"
    11  	"crypto/elliptic"
    12  	"crypto/rand"
    13  	"fmt"
    14  	"io/ioutil"
    15  	"os"
    16  	"path/filepath"
    17  	"testing"
    18  
    19  	"github.com/hyperledger/fabric-ca/lib"
    20  	dbutil "github.com/hyperledger/fabric-ca/lib/server/db/util"
    21  	. "github.com/hyperledger/fabric-ca/lib/server/idemix"
    22  	"github.com/hyperledger/fabric-ca/lib/server/idemix/mocks"
    23  	dmocks "github.com/hyperledger/fabric-ca/lib/server/idemix/mocks"
    24  	"github.com/hyperledger/fabric-ca/util"
    25  	"github.com/hyperledger/fabric/bccsp"
    26  	"github.com/hyperledger/fabric/idemix"
    27  	"github.com/kisielk/sqlstruct"
    28  	"github.com/pkg/errors"
    29  	"github.com/stretchr/testify/assert"
    30  )
    31  
    32  func TestNewIssuer(t *testing.T) {
    33  	lib := new(mocks.Lib)
    34  	cfg := &Config{
    35  		NonceExpiration:    "15",
    36  		NonceSweepInterval: "15",
    37  	}
    38  	issuer := NewIssuer("ca1", ".", cfg, util.GetDefaultBCCSP(), lib)
    39  	assert.NotNil(t, issuer)
    40  }
    41  
    42  func TestInit(t *testing.T) {
    43  	testdir, err := ioutil.TempDir(".", "issuerinittest")
    44  	if err != nil {
    45  		t.Fatalf("Failed to create temp directory: %s", err.Error())
    46  	}
    47  	defer os.RemoveAll(testdir)
    48  	err = os.MkdirAll(filepath.Join(testdir, "msp/keystore"), 0777)
    49  	if err != nil {
    50  		t.Fatalf("Failed to create directory: %s", err.Error())
    51  	}
    52  
    53  	db, issuer := getIssuer(t, testdir, false, false)
    54  	assert.NotNil(t, issuer)
    55  	err = issuer.Init(false, nil, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
    56  	assert.NoError(t, err, "Init should not return an error if db is nil")
    57  
    58  	err = issuer.Init(false, db, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
    59  	assert.NoError(t, err)
    60  
    61  	ik, err := issuer.IssuerPublicKey()
    62  	assert.NoError(t, err, "IssuerPublicKey should not return an error")
    63  	assert.NotNil(t, ik)
    64  	ctx := new(mocks.ServerRequestCtx)
    65  	ctx.On("IsBasicAuth").Return(true)
    66  	ctx.On("BasicAuthentication").Return("", errors.New("Authentication error"))
    67  	ctx.On("TokenAuthentication").Return("", errors.New("Authentication error"))
    68  	_, err = issuer.IssueCredential(ctx)
    69  	assert.Error(t, err, "IssuerCredential should fail")
    70  	_, err = issuer.GetCRI(ctx)
    71  	assert.Error(t, err, "GetCRI should fail")
    72  }
    73  
    74  func TestInitDBNotInitialized(t *testing.T) {
    75  	cfg := &Config{
    76  		NonceExpiration:    "15s",
    77  		NonceSweepInterval: "15m",
    78  	}
    79  	var db *dmocks.FabricCADB
    80  	issuer := NewIssuer("ca1", ".", cfg, util.GetDefaultBCCSP(), NewLib())
    81  	err := issuer.Init(false, db, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
    82  	assert.NoError(t, err)
    83  
    84  	db = new(dmocks.FabricCADB)
    85  	db.On("IsInitialized").Return(false)
    86  	issuer = NewIssuer("ca1", ".", cfg, util.GetDefaultBCCSP(), NewLib())
    87  	err = issuer.Init(false, db, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
    88  	assert.NoError(t, err)
    89  }
    90  
    91  func TestInitExistingIssuerCredential(t *testing.T) {
    92  	testdir, err := ioutil.TempDir(".", "issuerinittest")
    93  	if err != nil {
    94  		t.Fatalf("Failed to create temp directory: %s", err.Error())
    95  	}
    96  	defer os.RemoveAll(testdir)
    97  	err = os.MkdirAll(filepath.Join(testdir, "msp/keystore"), 0777)
    98  	if err != nil {
    99  		t.Fatalf("Failed to create directory: %s", err.Error())
   100  	}
   101  	err = lib.CopyFile(testPublicKeyFile, filepath.Join(testdir, "IssuerPublicKey"))
   102  	if err != nil {
   103  		t.Fatalf("Failed to copy file: %s", err.Error())
   104  	}
   105  	err = lib.CopyFile(testSecretKeyFile, filepath.Join(testdir, "msp/keystore/IssuerSecretKey"))
   106  	if err != nil {
   107  		t.Fatalf("Failed to copy file: %s", err.Error())
   108  	}
   109  
   110  	db, issuer := getIssuer(t, testdir, false, false)
   111  	assert.NotNil(t, issuer)
   112  
   113  	secrekeyfile := filepath.Join(testdir, "msp/keystore/IssuerSecretKey")
   114  	secrekeyFileInfo, err := os.Stat(secrekeyfile)
   115  	if err != nil {
   116  		t.Fatalf("os.Stat failed on test dir: %s", err)
   117  	}
   118  	oldmode := secrekeyFileInfo.Mode()
   119  	err = os.Chmod(secrekeyfile, 0000)
   120  	if err != nil {
   121  		t.Fatalf("Chmod on %s failed: %s", secrekeyFileInfo.Name(), err)
   122  	}
   123  	err = issuer.Init(false, db, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
   124  	assert.Error(t, err, "Init should fail if it fails to load issuer credential")
   125  
   126  	err = os.Chmod(secrekeyfile, oldmode)
   127  	if err != nil {
   128  		t.Fatalf("Chmod on %s failed: %s", testdir, err)
   129  	}
   130  	err = issuer.Init(false, db, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
   131  	assert.NoError(t, err)
   132  }
   133  func TestInitRenewTrue(t *testing.T) {
   134  	testdir, err := ioutil.TempDir(".", "issuerinittest")
   135  	if err != nil {
   136  		t.Fatalf("Failed to create temp directory: %s", err.Error())
   137  	}
   138  	defer os.RemoveAll(testdir)
   139  	db, issuer := getIssuer(t, testdir, true, false)
   140  	assert.NotNil(t, issuer)
   141  
   142  	err = issuer.Init(true, db, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
   143  	assert.Error(t, err, "Init should fail if it fails to generate random number")
   144  
   145  	db, issuer = getIssuer(t, testdir, false, true)
   146  	assert.NotNil(t, issuer)
   147  	err = issuer.Init(true, db, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
   148  	assert.Error(t, err, "Init should fail if it fails to create new issuer key")
   149  
   150  	db, issuer = getIssuer(t, testdir, false, false)
   151  	assert.NotNil(t, issuer)
   152  
   153  	testdataInfo, err := os.Stat(testdir)
   154  	if err != nil {
   155  		t.Fatalf("os.Stat failed on test dir: %s", err)
   156  	}
   157  	oldmode := testdataInfo.Mode()
   158  	err = os.Chmod(testdir, 0000)
   159  	if err != nil {
   160  		t.Fatalf("Chmod on %s failed: %s", testdataInfo.Name(), err)
   161  	}
   162  	defer func() {
   163  		err = os.Chmod(testdir, oldmode)
   164  		if err != nil {
   165  			t.Fatalf("Chmod on %s failed: %s", testdir, err)
   166  		}
   167  	}()
   168  	err = issuer.Init(true, db, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
   169  	assert.Error(t, err, "Init should fail if it fails to store issuer credential")
   170  }
   171  
   172  func TestVerifyTokenError(t *testing.T) {
   173  	testdir, err := ioutil.TempDir(".", "verifytokentesterror")
   174  	if err != nil {
   175  		t.Fatalf("Failed to create temp directory: %s", err.Error())
   176  	}
   177  	defer os.RemoveAll(testdir)
   178  
   179  	err = os.MkdirAll(filepath.Join(testdir, "msp/keystore"), 0777)
   180  	if err != nil {
   181  		t.Fatalf("Failed to create directory: %s", err.Error())
   182  	}
   183  	err = lib.CopyFile(testPublicKeyFile, filepath.Join(testdir, "IssuerPublicKey"))
   184  	if err != nil {
   185  		t.Fatalf("Failed to copy file: %s", err.Error())
   186  	}
   187  	err = lib.CopyFile(testSecretKeyFile, filepath.Join(testdir, "msp/keystore/IssuerSecretKey"))
   188  	if err != nil {
   189  		t.Fatalf("Failed to copy file: %s", err.Error())
   190  	}
   191  
   192  	db, issuer := getIssuer(t, testdir, false, false)
   193  	assert.NotNil(t, issuer)
   194  
   195  	_, err = issuer.VerifyToken("idemix.1.foo.blah", "", "", []byte{})
   196  	assert.Error(t, err, "VerifyToken should fail as issuer is not initialized")
   197  
   198  	err = issuer.Init(false, db, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
   199  	assert.NoError(t, err)
   200  
   201  	_, err = issuer.VerifyToken("idemix.1.foo", "", "", []byte{})
   202  	assert.Error(t, err, "VerifyToken should fail if the auth header does not have four parts separated by '.'")
   203  
   204  	_, err = issuer.VerifyToken("idemix.2.foo.bar", "", "", []byte{})
   205  	assert.Error(t, err, "VerifyToken should fail if the auth header does not have correct version")
   206  
   207  	db.On("Rebind", SelectCredentialByIDSQL).Return(SelectCredentialByIDSQL)
   208  	credRecords := []CredRecord{}
   209  	sqlstr := fmt.Sprintf(SelectCredentialByIDSQL, sqlstruct.Columns(CredRecord{}))
   210  	db.On("Select", "GetCredentialsByID", &credRecords, sqlstr, "foo").Return(errors.New("db error getting creds for user"))
   211  
   212  	_, err = issuer.VerifyToken("idemix.1.foo.sig", "", "", []byte{})
   213  	assert.Error(t, err, "VerifyToken should fail if there is error looking up enrollment id in the database")
   214  }
   215  
   216  func TestVerifyTokenNoCreds(t *testing.T) {
   217  	testdir, err := ioutil.TempDir(".", "verifytokentestnocreds")
   218  	if err != nil {
   219  		t.Fatalf("Failed to create temp directory: %s", err.Error())
   220  	}
   221  	defer os.RemoveAll(testdir)
   222  
   223  	err = os.MkdirAll(filepath.Join(testdir, "msp/keystore"), 0777)
   224  	if err != nil {
   225  		t.Fatalf("Failed to create directory: %s", err.Error())
   226  	}
   227  	err = lib.CopyFile(testPublicKeyFile, filepath.Join(testdir, "IssuerPublicKey"))
   228  	if err != nil {
   229  		t.Fatalf("Failed to copy file: %s", err.Error())
   230  	}
   231  	err = lib.CopyFile(testSecretKeyFile, filepath.Join(testdir, "msp/keystore/IssuerSecretKey"))
   232  	if err != nil {
   233  		t.Fatalf("Failed to copy file: %s", err.Error())
   234  	}
   235  
   236  	db, issuer := getIssuer(t, testdir, false, false)
   237  	assert.NotNil(t, issuer)
   238  
   239  	err = issuer.Init(false, db, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
   240  	assert.NoError(t, err)
   241  
   242  	db.On("Rebind", SelectCredentialByIDSQL).Return(SelectCredentialByIDSQL)
   243  	credRecords := []CredRecord{}
   244  	sqlstr := fmt.Sprintf(SelectCredentialByIDSQL, sqlstruct.Columns(CredRecord{}))
   245  	f := getCredsSelectFunc(t, &credRecords, false)
   246  	db.On("Select", "GetCredentialsByID", &credRecords, sqlstr, "foo").Return(f)
   247  
   248  	_, err = issuer.VerifyToken("idemix.1.foo.sig", "", "", []byte{})
   249  	assert.Error(t, err, "VerifyToken should fail if the enrollment id does not have creds")
   250  }
   251  
   252  func TestVerifyTokenBadSignatureEncoding(t *testing.T) {
   253  	testdir, err := ioutil.TempDir(".", "verifytokentestbadsigencoding")
   254  	if err != nil {
   255  		t.Fatalf("Failed to create temp directory: %s", err.Error())
   256  	}
   257  	defer os.RemoveAll(testdir)
   258  
   259  	err = os.MkdirAll(filepath.Join(testdir, "msp/keystore"), 0777)
   260  	if err != nil {
   261  		t.Fatalf("Failed to create directory: %s", err.Error())
   262  	}
   263  	err = lib.CopyFile(testPublicKeyFile, filepath.Join(testdir, "IssuerPublicKey"))
   264  	if err != nil {
   265  		t.Fatalf("Failed to copy file: %s", err.Error())
   266  	}
   267  	err = lib.CopyFile(testSecretKeyFile, filepath.Join(testdir, "msp/keystore/IssuerSecretKey"))
   268  	if err != nil {
   269  		t.Fatalf("Failed to copy file: %s", err.Error())
   270  	}
   271  
   272  	db, issuer := getIssuer(t, testdir, false, false)
   273  	assert.NotNil(t, issuer)
   274  
   275  	err = issuer.Init(false, db, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
   276  	assert.NoError(t, err)
   277  
   278  	db.On("Rebind", SelectCredentialByIDSQL).Return(SelectCredentialByIDSQL)
   279  	credRecords := []CredRecord{}
   280  	sqlstr := fmt.Sprintf(SelectCredentialByIDSQL, sqlstruct.Columns(CredRecord{}))
   281  	f := getCredsSelectFunc(t, &credRecords, true)
   282  	db.On("Select", "GetCredentialsByID", &credRecords, sqlstr, "foo").Return(f)
   283  
   284  	_, err = issuer.VerifyToken("idemix.1.foo.sig", "", "", []byte{})
   285  	assert.Error(t, err, "VerifyToken should fail if the signature is not in base64 format")
   286  	assert.NotEqual(t, err.Error(), "errer")
   287  }
   288  
   289  func TestVerifyTokenBadSignature(t *testing.T) {
   290  	testdir, err := ioutil.TempDir(".", "verifytokentestbadsig")
   291  	if err != nil {
   292  		t.Fatalf("Failed to create temp directory: %s", err.Error())
   293  	}
   294  	defer os.RemoveAll(testdir)
   295  
   296  	err = os.MkdirAll(filepath.Join(testdir, "msp/keystore"), 0777)
   297  	if err != nil {
   298  		t.Fatalf("Failed to create directory: %s", err.Error())
   299  	}
   300  	err = lib.CopyFile(testPublicKeyFile, filepath.Join(testdir, "IssuerPublicKey"))
   301  	if err != nil {
   302  		t.Fatalf("Failed to copy file: %s", err.Error())
   303  	}
   304  	err = lib.CopyFile(testSecretKeyFile, filepath.Join(testdir, "msp/keystore/IssuerSecretKey"))
   305  	if err != nil {
   306  		t.Fatalf("Failed to copy file: %s", err.Error())
   307  	}
   308  
   309  	db, issuer := getIssuer(t, testdir, false, false)
   310  	assert.NotNil(t, issuer)
   311  
   312  	err = issuer.Init(false, db, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
   313  	assert.NoError(t, err)
   314  
   315  	db.On("Rebind", SelectCredentialByIDSQL).Return(SelectCredentialByIDSQL)
   316  	credRecords := []CredRecord{}
   317  	sqlstr := fmt.Sprintf(SelectCredentialByIDSQL, sqlstruct.Columns(CredRecord{}))
   318  	f := getCredsSelectFunc(t, &credRecords, true)
   319  	db.On("Select", "GetCredentialsByID", &credRecords, sqlstr, "admin").Return(f)
   320  
   321  	sig := util.B64Encode([]byte("hello"))
   322  	_, err = issuer.VerifyToken("idemix.1.admin."+sig, "", "", []byte{})
   323  	assert.Error(t, err, "VerifyToken should fail if the signature is not valid")
   324  
   325  	digest, err := util.GetDefaultBCCSP().Hash([]byte(sig), &bccsp.SHAOpts{})
   326  	if err != nil {
   327  		t.Fatalf("Failed to get hash of the message: %s", err.Error())
   328  	}
   329  	_, err = issuer.VerifyToken("idemix.1.admin.CkQKIAoanxNH9nO5ivQy94e+DH+SiwkkBhYeNbtyQhM1HD7FEiBbBcMVcCW9HoJe5KWMtyvO6a4UtB4xo2x/SV7xvxcVvBJECiBugYjF0AZ8lWvaeKCXtEbPvawQye7RK0m5SpQzEwcu/RIgioEuVacQR5DroKwgAZi3ALClpCLJFjlRwVv7w2zJcQQaRAogeAU3ZnfcA60kGIm6gHKGTRrI3O9sbkpdHt/UIF+Tz5sSIHGfTP5B7Ocb43q3sewpuqIjDyvFEzIeBpummJD4MPB5IiAewOhliKfwXta7pSCIMlfKqmuJbhAwhJl7vJdhfEW05iogGY6MfvsdO+HvQdSmlIexEBgl51KsFCO6MrAZbms/hLAyIHbqzC8f7sliJ6Hzn65JZKUyHXiAnOM3iydZ7gntoYXxOiClzG32BL3M4MyQGHz6SP8Aozxh3u0dATr0uxOOI6p94EIgO90ealPZ51ZXP+JsAWwLePpyX+lgegF0Gp002uFyv0tKIFRSBfhnRqm7Dk1VbG1hSsl7AJU8nzzYZJZKHRFrhdvGUiCWUu3nvjr5TEFtF5eOMp5XTPXmUNTq8k3SLckY1o35mlIgOeJtkxDc7NtKAiF+cz+cIsv1MIQ3qGXj0nwoMjnHvMJSIALGJWjFKVhK9B9P8BOkO03iMwzNJJdSeA8MIRGyk5WCWiCGix0AHQA29jHVOCaCrBZUVlqBRLa5Kzpftk0jp3LKXmJECiDheCgd36mEjsr1D4Sm+cbtE3XKAdRI2dLq5bFQZqN4/RIgNbxez4+fxVsRuGu8ooFkfem2C5/+1z3QDzyu8fu3fyVqID34eII73Km/SviYxAoHZ91HXIHXhGwid4DFO+xuGI7ycogBCiD+DDNQtMlsIChWD1d8KJE6zhxTmhK/hDzSJha2icCe+xIgTqZgV3OKwFTbWuHGN9gTuSTdeOKH0DWJ0mntNKN+aisaIHAgRufFQqOzdncNdRJOPlHvyyR1jWFYSOkJtIG+3Cf/IiAFVOO804jCkELupkkpfrKfi0y+gIIamLPgEoERSq0Em3pgkd4c0QZIUDeyRVBgwDj7aTk8J+xzdGZSCgIt8RpuKoxmfuDV2SlFfw/fVZqfPH02+jYeyqxbf7FD8vo5dstEpLHy86Yno6zr1bXLDLe34r2XIIH6KrYFI3gYAsQhzzd/gAEBigEA", "", "", digest)
   330  	assert.Error(t, err, "VerifyToken should fail signature is valid but verification fails")
   331  }
   332  
   333  func TestIsToken(t *testing.T) {
   334  	token := "idemixx.1.foo.blah"
   335  	assert.False(t, IsToken(token))
   336  	token = "foo.sig"
   337  	assert.False(t, IsToken(token))
   338  	token = "idemix.1.foo.sig"
   339  	assert.True(t, IsToken(token))
   340  }
   341  
   342  func TestRevocationPublicKey(t *testing.T) {
   343  	testdir, err := ioutil.TempDir(".", "revocationpubkeytest")
   344  	if err != nil {
   345  		t.Fatalf("Failed to create temp directory: %s", err.Error())
   346  	}
   347  	defer os.RemoveAll(testdir)
   348  
   349  	err = os.MkdirAll(filepath.Join(testdir, "msp/keystore"), 0777)
   350  	if err != nil {
   351  		t.Fatalf("Failed to create directory: %s", err.Error())
   352  	}
   353  	err = lib.CopyFile(testPublicKeyFile, filepath.Join(testdir, "IssuerPublicKey"))
   354  	if err != nil {
   355  		t.Fatalf("Failed to copy file: %s", err.Error())
   356  	}
   357  	err = lib.CopyFile(testSecretKeyFile, filepath.Join(testdir, "msp/keystore/IssuerSecretKey"))
   358  	if err != nil {
   359  		t.Fatalf("Failed to copy file: %s", err.Error())
   360  	}
   361  
   362  	db, issuer := getIssuer(t, testdir, false, false)
   363  	assert.NotNil(t, issuer)
   364  
   365  	err = issuer.Init(false, db, &dbutil.Levels{Credential: 1, RAInfo: 1, Nonce: 1})
   366  	assert.NoError(t, err, "Init should not return an error")
   367  
   368  	_, err = issuer.RevocationPublicKey()
   369  	assert.NoError(t, err, "RevocationPublicKey should not return an error")
   370  }
   371  
   372  func getIssuer(t *testing.T, testDir string, getranderror, newIssuerKeyerror bool) (*dmocks.FabricCADB, Issuer) {
   373  	err := os.MkdirAll(filepath.Join(testDir, "msp/keystore"), 0777)
   374  	if err != nil {
   375  		t.Fatalf("Failed to create directory: %s", err.Error())
   376  	}
   377  
   378  	db := new(dmocks.FabricCADB)
   379  
   380  	tx := new(dmocks.FabricCATx)
   381  	tx.On("Commit").Return(nil)
   382  	tx.On("Rollback").Return(nil)
   383  	tx.On("Rebind", SelectRAInfo).Return(SelectRAInfo)
   384  	tx.On("Rebind", UpdateNextHandle).Return(UpdateNextHandle)
   385  	tx.On("Exec", UpdateNextHandle, 2, 1).Return(nil, nil)
   386  	rcInfos := []RevocationAuthorityInfo{}
   387  	f1 := getTxSelectFunc(t, &rcInfos, 1, false, true)
   388  	tx.On("Select", &rcInfos, SelectRAInfo).Return(f1)
   389  
   390  	db.On("BeginTx").Return(tx)
   391  	db.On("IsInitialized").Return(true)
   392  
   393  	lib := new(mocks.Lib)
   394  	rnd, err := idemix.GetRand()
   395  	if err != nil {
   396  		t.Fatalf("Failed to get random number: %s", err.Error())
   397  	}
   398  	ik, err := idemix.NewIssuerKey(GetAttributeNames(), rnd)
   399  	if err != nil {
   400  		t.Fatalf("Failed to generate issuer key: %s", err.Error())
   401  	}
   402  	if getranderror {
   403  		lib.On("GetRand").Return(nil, errors.New("Failed to generate random number"))
   404  	} else {
   405  		lib.On("GetRand").Return(rnd, nil)
   406  	}
   407  
   408  	if newIssuerKeyerror {
   409  		lib.On("NewIssuerKey", GetAttributeNames(), rnd).Return(nil, errors.New("Failed to generate new issuer key"))
   410  	} else {
   411  		lib.On("NewIssuerKey", GetAttributeNames(), rnd).Return(ik, nil)
   412  	}
   413  
   414  	key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
   415  	if err != nil {
   416  		t.Fatalf("Failed to generate key: %s", err.Error())
   417  	}
   418  	lib.On("GenerateLongTermRevocationKey").Return(key, nil)
   419  
   420  	cfg := &Config{
   421  		RHPoolSize:         100,
   422  		NonceExpiration:    "15s",
   423  		NonceSweepInterval: "15m",
   424  	}
   425  	issuer := NewIssuer("ca1", testDir, cfg, util.GetDefaultBCCSP(), lib)
   426  
   427  	f := getSelectFunc(t, true, false)
   428  
   429  	rcInfosForSelect := []RevocationAuthorityInfo{}
   430  	db.On("Select", "GetRAInfo", &rcInfosForSelect, SelectRAInfo).Return(f)
   431  	rcinfo := RevocationAuthorityInfo{
   432  		Epoch:                1,
   433  		NextRevocationHandle: 1,
   434  		LastHandleInPool:     100,
   435  		Level:                1,
   436  	}
   437  	result := new(dmocks.Result)
   438  	result.On("RowsAffected").Return(int64(1), nil)
   439  	db.On("NamedExec", "AddRAInfo", InsertRAInfo, &rcinfo).Return(result, nil)
   440  
   441  	return db, issuer
   442  }
   443  
   444  func getCredsSelectFunc(t *testing.T, creds *[]CredRecord, isAppend bool) func(string, interface{}, string, ...interface{}) error {
   445  	return func(funcName string, dest interface{}, query string, args ...interface{}) error {
   446  		credRecs := dest.(*[]CredRecord)
   447  		cred := CredRecord{
   448  			ID:     "foo",
   449  			Status: "active",
   450  			Cred:   "",
   451  		}
   452  
   453  		if isAppend {
   454  			//*creds = append(*creds, cred)
   455  			*credRecs = append(*credRecs, cred)
   456  		}
   457  		return nil
   458  	}
   459  }