code: func (n *NymSignatureScheme) Sign(sk handlers.Big, Nym handlers.Ecp, RNym handlers.Big, ipk handlers.IssuerPublicKey, digest []byte) (res []byte, err error) {
  	defer func() {
  		if r := recover(); r != nil {
  			res = nil
  			err = errors.Errorf("failure [%s]", r)
  		}
  	}()
  
  	isk, ok := sk.(*Big)
  	if !ok {
  		return nil, errors.Errorf("invalid user secret key, expected *Big, got [%T]", sk)
  	}
  	inym, ok := Nym.(*Ecp)
  	if !ok {
  		return nil, errors.Errorf("invalid nym public key, expected *Ecp, got [%T]", Nym)
  	}
  	irnym, ok := RNym.(*Big)
  	if !ok {
  		return nil, errors.Errorf("invalid nym secret key, expected *Big, got [%T]", RNym)
  	}
  	iipk, ok := ipk.(*IssuerPublicKey)
  	if !ok {
  		return nil, errors.Errorf("invalid issuer public key, expected *IssuerPublicKey, got [%T]", ipk)
  	}
  
  	sig, err := cryptolib.NewNymSignature(
  		isk.E,
  		inym.E,
  		irnym.E,
  		iipk.PK,
  		digest,
  		n.NewRand())
  	if err != nil {
  		return nil, errors.WithMessage(err, "failed creating new nym signature")
  	}
  
  	return proto.Marshal(sig)
  }
docs: // Sign produces a signature over the passed digest. It takes in input, the user secret key (sk),
  // the pseudonym public key (Nym) and secret key (RNym), and the issuer public key (ipk).