// WritePrivKey will write the private key into the filename given // It takes a suite in order to adequatly write the secret // Returns an error if anything went wrong during file handling or writing key func WritePrivKey(suite abstract.Suite, fileName string, priv abstract.Secret) error { // Opening file privFile, err := os.OpenFile(fileName, os.O_TRUNC|os.O_WRONLY|os.O_CREATE, 0744) if err != nil { return err } defer privFile.Close() // Writing down ! err = suite.Write(privFile, priv) if err != nil { return err } privFile.WriteString("\n") return nil }
// This simplified implementation of Schnorr Signatures is based on // crypto/anon/sig.go // The ring structure is removed and // The anonimity set is reduced to one public key = no anonimity func SchnorrSign(suite abstract.Suite, random cipher.Stream, message []byte, privateKey abstract.Scalar) []byte { // Create random secret v and public point commitment T v := suite.Scalar().Pick(random) T := suite.Point().Mul(nil, v) // Create challenge c based on message and T c := hashSchnorr(suite, message, T) // Compute response r = v - x*c r := suite.Scalar() r.Mul(privateKey, c).Sub(v, r) // Return verifiable signature {c, r} // Verifier will be able to compute v = r + x*c // And check that hashElgamal for T and the message == c buf := bytes.Buffer{} sig := basicSig{c, r} suite.Write(&buf, &sig) return buf.Bytes() }
// Generate a new public/private keypair with the given ciphersuite // and Save it to the application's previously-loaded configuration. func (f *File) GenKey(keys *Keys, suite abstract.Suite) (KeyPair, error) { // Create the map if it doesn't exist // if *keys == nil { // *keys = make(map[string] KeyInfo) // } // Create a fresh public/private keypair p := KeyPair{} p.Gen(suite, random.Stream) pubId := p.PubId() // Write the private key file secname := f.dirName + "/sec-" + pubId r := util.Replacer{} if err := r.Open(secname); err != nil { return KeyPair{}, err } defer r.Abort() // Write the secret key if err := suite.Write(r.File, &p.Secret); err != nil { return KeyPair{}, err } // Commit the secret key if err := r.Commit(); err != nil { return KeyPair{}, err } // Re-write the config file with the new public key *keys = append(*keys, KeyInfo{suite.String(), pubId}) if err := f.Save(); err != nil { return KeyPair{}, err } return p, nil }
// Sign creates an optionally anonymous, optionally linkable // signature on a given message. // // The caller supplies one or more public keys representing an anonymity set, // and the private key corresponding to one of those public keys. // The resulting signature proves to a verifier that the owner of // one of these public keys signed the message, // without revealing which key-holder signed the message, // offering anonymity among the members of this explicit anonymity set. // The other users whose keys are listed in the anonymity set need not consent // or even be aware that they have been included in an anonymity set: // anyone having a suitable public key may be "conscripted" into a set. // // If the provided anonymity set contains only one public key (the signer's), // then this function produces a traditional non-anonymous signature, // equivalent in both size and performance to a standard ElGamal signature. // // The caller may request either unlinkable or linkable anonymous signatures. // If linkScope is nil, this function generates an unlinkable signature, // which contains no information about which member signed the message. // The anonymity provided by unlinkable signatures is forward-secure, // in that a signature reveals nothing about which member generated it, // even if all members' private keys are later released. // For cryptographic background on unlinkable anonymity-set signatures - // also known as ring signatures or ad-hoc group signatures - // see Rivest, "How to Leak a Secret" at // http://people.csail.mit.edu/rivest/RivestShamirTauman-HowToLeakASecret.pdf. // // If the caller passes a non-nil linkScope, // the resulting anonymous signature will be linkable. // This means that given two signatures produced using the same linkScope, // a verifier will be able to tell whether // the same or different anonymity set members produced those signatures. // In particular, verifying a linkable signature yields a linkage tag. // This linkage tag has a 1-to-1 correspondence with the signer's public key // within a given linkScope, but is cryptographically unlinkable // to either the signer's public key or to linkage tags in other scopes. // The provided linkScope may be an arbitrary byte-string; // the only significance these scopes have is whether they are equal or unequal. // For details on the linkable signature algorithm this function implements, // see Liu/Wei/Wong, // "Linkable Spontaneous Anonymous Group Signature for Ad Hoc Groups" at // http://www.cs.cityu.edu.hk/~duncan/papers/04liuetal_lsag.pdf. // // Linkage tags may be used to protect against sock-puppetry or Sybil attacks // in situations where a verifier needs to know how many distinct members // of an anonymity set are present or signed messages in a given context. // It is cryptographically hard for one anonymity set member // to produce signatures with different linkage tags in the same scope. // An important and fundamental downside, however, is that // linkable signatures do NOT offer forward-secure anonymity. // If an anonymity set member's private key is later released, // it is trivial to check whether or not that member produced a given signature. // Also, anonymity set members who did NOT sign a message could // (voluntarily or under coercion) prove that they did not sign it, // e.g., simply by signing some other message in that linkage context // and noting that the resulting linkage tag comes out different. // Thus, linkable anonymous signatures are not appropriate to use // in situations where there may be significant risk // that members' private keys may later be compromised, // or that members may be persuaded or coerced into revealing whether or not // they produced a signature of interest. // func Sign(suite abstract.Suite, random cipher.Stream, message []byte, anonymitySet Set, linkScope []byte, mine int, privateKey abstract.Secret) []byte { // Note that Rivest's original ring construction directly supports // heterogeneous rings containing public keys of different types - // e.g., a mixture of RSA keys and DSA keys with varying parameters. // Our ring signature construction currently supports // only homogeneous rings containing compatible keys // drawn from the cipher suite (e.g., the same elliptic curve). // The upside to this constrint is greater flexibility: // e.g., we also easily obtain linkable ring signatures, // which are not readily feasible with the original ring construction. n := len(anonymitySet) // anonymity set size L := []abstract.Point(anonymitySet) // public keys in anonymity set pi := mine // If we want a linkable ring signature, produce correct linkage tag, // as a pseudorandom base point multiplied by our private key. // Liu's scheme specifies the linkScope as a hash of the ring; // this is one reasonable choice of linkage scope, // but there are others, so we parameterize this choice. var linkBase, linkTag abstract.Point if linkScope != nil { linkStream := suite.Cipher(linkScope) linkBase, _ = suite.Point().Pick(nil, linkStream) linkTag = suite.Point().Mul(linkBase, privateKey) } // First pre-hash the parameters to H1 // that are invariant for different ring positions, // so that we don't have to hash them many times. H1pre := signH1pre(suite, linkScope, linkTag, message) // Pick a random commit for my ring position u := suite.Secret().Pick(random) var UB, UL abstract.Point UB = suite.Point().Mul(nil, u) if linkScope != nil { UL = suite.Point().Mul(linkBase, u) } // Build the challenge ring s := make([]abstract.Secret, n) c := make([]abstract.Secret, n) c[(pi+1)%n] = signH1(suite, H1pre, UB, UL) var P, PG, PH abstract.Point P = suite.Point() PG = suite.Point() if linkScope != nil { PH = suite.Point() } for i := (pi + 1) % n; i != pi; i = (i + 1) % n { s[i] = suite.Secret().Pick(random) PG.Add(PG.Mul(nil, s[i]), P.Mul(L[i], c[i])) if linkScope != nil { PH.Add(PH.Mul(linkBase, s[i]), P.Mul(linkTag, c[i])) } c[(i+1)%n] = signH1(suite, H1pre, PG, PH) //fmt.Printf("s%d %s\n",i,s[i].String()) //fmt.Printf("c%d %s\n",(i+1)%n,c[(i+1)%n].String()) } s[pi] = suite.Secret() s[pi].Mul(privateKey, c[pi]).Sub(u, s[pi]) // s_pi = u - x_pi c_pi // Encode and return the signature buf := bytes.Buffer{} if linkScope != nil { // linkable ring signature sig := lSig{uSig{c[0], s}, linkTag} suite.Write(&buf, &sig) } else { // unlinkable ring signature sig := uSig{c[0], s} suite.Write(&buf, &sig) } return buf.Bytes() }
func write64(suite abstract.Suite, wc io.WriteCloser, data ...interface{}) error { if err := suite.Write(wc, data); err != nil { return err } return wc.Close() }
func WriteSecret64(suite abstract.Suite, w io.Writer, secret abstract.Secret) error { enc := base64.NewEncoder(base64.StdEncoding, w) err := suite.Write(enc, secret) enc.Close() return err }
// Write a public point to a base64 representation func WritePub64(suite abstract.Suite, w io.Writer, point abstract.Point) error { enc := base64.NewEncoder(base64.StdEncoding, w) err := suite.Write(enc, point) enc.Close() return err }