Documentation ¶
Overview ¶
Package anon implements cryptographic primitives for anonymous communication.
Index ¶
- func Decrypt(suite Suite, ciphertext []byte, anonymitySet Set, mine int, ...) ([]byte, error)
- func Encrypt(suite Suite, message []byte, anonymitySet Set) []byte
- func Sign(suite Suite, message []byte, anonymitySet Set, linkScope []byte, mine int, ...) []byte
- func Verify(suite Suite, message []byte, anonymitySet Set, linkScope []byte, ...) ([]byte, error)
- type Set
- type Suite
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Decrypt ¶
func Decrypt(suite Suite, ciphertext []byte, anonymitySet Set, mine int, privateKey kyber.Scalar) ([]byte, error)
Decrypt a message encrypted for a particular anonymity set. Returns the cleartext message on success, or an error on failure.
The caller provides the anonymity set for which the message is intended, and the private key corresponding to one of the public keys in the set. Decrypt verifies that the message is encrypted correctly for this set - in particular, that it could be decrypted by ALL of the listed members - before returning successfully with the decrypted message.
This verification ensures that a malicious sender cannot de-anonymize a receiver by constructing a ciphertext incorrectly so as to be decryptable by only some members of the set. As a side-effect, this verification also ensures plaintext-awareness: that is, it is infeasible for a sender to construct any ciphertext that will be accepted by the receiver without knowing the plaintext.
func Encrypt ¶
Encrypt a message for reading by any member of an explit anonymity set. The caller supplies one or more keys representing the anonymity set. If the provided set contains only one public key, this reduces to conventional single-receiver public-key encryption.
Example (AnonSet) ¶
// Crypto setup: Get a suite which returns a predictable // random number stream for this example. // In production, simply use edwards25519.NewBlakeSHA256Ed25519() suite := edwards25519.NewBlakeSHA256Ed25519WithRand(blake2xb.New(nil)) // Create an anonymity set of random "public keys" X := make([]kyber.Point, 3) for i := range X { // pick random points X[i] = suite.Point().Pick(suite.RandomStream()) } // Make just one of them an actual public/private keypair (X[mine],x) mine := 1 // only the signer knows this x := suite.Scalar().Pick(suite.RandomStream()) // create a private key x X[mine] = suite.Point().Mul(x, nil) // corresponding public key X // Encrypt a message with all the public keys M := []byte("Hello World!") // message to encrypt C := Encrypt(suite, M, Set(X)) fmt.Printf("Encryption of '%s':\n%s", string(M), hex.Dump(C)) // Decrypt the ciphertext with the known private key MM, err := Decrypt(suite, C, Set(X), mine, x) if err != nil { panic(err.Error()) } if !bytes.Equal(M, MM) { panic("Decryption failed to reproduce message") } fmt.Printf("Decrypted: '%s'\n", string(MM))
Output: Encryption of 'Hello World!': 00000000 c3 c2 10 b2 dc 66 58 f7 6d 3b 65 a4 c6 b9 2a d5 |.....fX.m;e...*.| 00000010 3f 8d f8 68 41 92 c7 84 ef 7d a1 6c 59 89 d0 bc |?..hA....}.lY...| 00000020 ea 60 08 5f f4 ab 35 48 08 be 85 be e8 58 fa 84 |.`._..5H.....X..| 00000030 ea 97 d0 57 10 01 c4 bc 9f 65 18 a6 4c e1 d2 b9 |...W.....e..L...| 00000040 df 81 4a 63 da 92 56 49 20 f4 8a 9e ff d5 52 42 |..Jc..VI .....RB| 00000050 8d bd 28 b7 b3 61 3b 1c 89 12 cc 4b 8e d9 c0 7b |..(..a;....K...{| 00000060 7d f5 d8 53 c9 9f cf e9 cc 68 35 d3 e8 bc 21 b1 |}..S.....h5...!.| 00000070 01 7d ae b4 b0 eb 5b c0 ad b7 c7 b6 c5 9c 01 df |.}....[.........| 00000080 7c 35 28 21 1a 04 94 de ba 0f 42 6e b9 9f bb c5 ||5(!......Bn....| 00000090 1e 37 4d ab 06 63 d2 37 97 d5 45 2a |.7M..c.7..E*| Decrypted: 'Hello World!'
Example (One) ¶
// Crypto setup: Get a suite which returns a predictable // random number stream for this example. // In production, simply use edwards25519.NewBlakeSHA256Ed25519() suite := edwards25519.NewBlakeSHA256Ed25519WithRand(blake2xb.New(nil)) // Create a public/private keypair (X[mine],x) X := make([]kyber.Point, 1) mine := 0 // which public key is mine x := suite.Scalar().Pick(suite.RandomStream()) // create a private key x X[mine] = suite.Point().Mul(x, nil) // corresponding public key X // Encrypt a message with the public key M := []byte("Hello World!") C := Encrypt(suite, M, Set(X)) fmt.Printf("Encryption of '%s':\n%s", string(M), hex.Dump(C)) // Decrypt the ciphertext with the private key MM, err := Decrypt(suite, C, Set(X), mine, x) if err != nil { panic(err.Error()) } if !bytes.Equal(M, MM) { panic("Decryption failed to reproduce message") } fmt.Printf("Decrypted: '%s'\n", string(MM))
Output: Encryption of 'Hello World!': 00000000 82 ea 76 3b 11 5f ee b2 ac 08 62 af 84 52 1c 0c |..v;._....b..R..| 00000010 e9 1d 7d 15 b5 44 2e 65 cb 19 45 49 45 f0 10 8f |..}..D.e..EIE...| 00000020 7b c3 0c 03 22 67 9f 54 9a 44 52 a9 bb ac 51 07 |{..."g.T.DR...Q.| 00000030 c8 98 9d 5d dd 54 11 e3 9f a9 7c 44 b5 c7 bf f8 |...].T....|D....| 00000040 23 af 58 fb 5f 40 2d 92 e9 63 fe 71 13 33 e0 ce |#.X._@-..c.q.3..| 00000050 65 83 88 45 3c 88 3f bd 2f bd 3a 03 |e..E<.?./.:.| Decrypted: 'Hello World!'
func Sign ¶
func Sign(suite Suite, message []byte, anonymitySet Set, linkScope []byte, mine int, privateKey kyber.Scalar) []byte
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 https://people.csail.mit.edu/rivest/pubs/RST01.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 https://eprint.iacr.org/2004/027.
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.
Example (AnonSet) ¶
This example demonstrates how to create unlinkable anonymity-set signatures, and to verify them, using a small anonymity set containing three public keys.
// Crypto setup: Get a suite which returns a predictable // random number stream for this example. // In production, simply use edwards25519.NewBlakeSHA256Ed25519() suite := edwards25519.NewBlakeSHA256Ed25519WithRand(blake2xb.New(nil)) // Create an anonymity set of random "public keys" X := make([]kyber.Point, 3) for i := range X { // pick random points X[i] = suite.Point().Pick(suite.RandomStream()) } // Make just one of them an actual public/private keypair (X[mine],x) mine := 1 // only the signer knows this x := suite.Scalar().Pick(suite.RandomStream()) // create a private key x X[mine] = suite.Point().Mul(x, nil) // corresponding public key X // Generate the signature M := []byte("Hello World!") // message we want to sign sig := Sign(suite, M, Set(X), nil, mine, x) fmt.Print("Signature:\n" + hex.Dump(sig)) // Verify the signature against the correct message tag, err := Verify(suite, M, Set(X), nil, sig) if err != nil { panic(err.Error()) } if tag == nil || len(tag) != 0 { panic("Verify returned wrong tag") } fmt.Println("Signature verified against correct message.") // Verify the signature against the wrong message BAD := []byte("Goodbye world!") tag, err = Verify(suite, BAD, Set(X), nil, sig) if err == nil || tag != nil { panic("Signature verified against wrong message!?") } fmt.Println("Verifying against wrong message: " + err.Error())
Output: Signature: 00000000 dc 43 94 ce 5e c5 ab c1 f8 3e bd e1 30 a8 19 bd |.C..^....>..0...| 00000010 13 f7 b4 0d f0 f5 39 40 c3 de 71 26 f9 1c ba 0f |......9@..q&....| 00000020 61 f7 23 a0 e6 7c 95 b7 e4 b2 32 55 40 d4 25 87 |a.#..|....2U@.%.| 00000030 da d4 76 18 01 22 fb c7 93 f7 40 6b d6 e0 e7 0b |..v.."....@k....| 00000040 3d a3 1f 32 50 f8 c1 d2 c6 93 f4 19 e0 c7 2a 06 |=..2P.........*.| 00000050 ef 6f 1c 4d c9 4f 0e db c8 30 4d 20 94 52 e8 04 |.o.M.O...0M .R..| 00000060 f4 6d eb 7c 5f 30 09 60 bf c7 37 cd 44 16 fe bb |.m.|_0.`..7.D...| 00000070 b6 5a e5 45 b3 6c 7f b1 12 6d 60 b9 9f 60 0e 0c |.Z.E.l...m`..`..| Signature verified against correct message. Verifying against wrong message: invalid signature
Example (Linkable) ¶
This example demonstrates the creation of linkable anonymity set signatures, and verification, using an anonymity set containing three public keys. We produce four signatures, two from each of two private key-holders, demonstrating how the resulting verifiable tags distinguish signatures by the same key-holder from signatures by different key-holders.
// Crypto setup: Get a suite which returns a predictable // random number stream for this example. // In production, simply use edwards25519.NewBlakeSHA256Ed25519() suite := edwards25519.NewBlakeSHA256Ed25519WithRand(blake2xb.New(nil)) rand := suite.RandomStream() // Create an anonymity set of random "public keys" X := make([]kyber.Point, 3) for i := range X { // pick random points X[i] = suite.Point().Pick(rand) } // Make two actual public/private keypairs (X[mine],x) mine1 := 1 // only the signer knows this mine2 := 2 x1 := suite.Scalar().Pick(rand) // create a private key x x2 := suite.Scalar().Pick(rand) X[mine1] = suite.Point().Mul(x1, nil) // corresponding public key X X[mine2] = suite.Point().Mul(x2, nil) // Generate two signatures using x1 and two using x2 M := []byte("Hello World!") // message we want to sign S := []byte("My Linkage Scope") // scope for linkage tags var sig [4][]byte sig[0] = Sign(suite, M, Set(X), S, mine1, x1) sig[1] = Sign(suite, M, Set(X), S, mine1, x1) sig[2] = Sign(suite, M, Set(X), S, mine2, x2) sig[3] = Sign(suite, M, Set(X), S, mine2, x2) for i := range sig { fmt.Printf("Signature %d:\n%s", i, hex.Dump(sig[i])) } // Verify the signatures against the correct message var tag [4][]byte for i := range sig { goodtag, err := Verify(suite, M, Set(X), S, sig[i]) if err != nil { panic(err.Error()) } tag[i] = goodtag if tag[i] == nil || len(tag[i]) != suite.PointLen() { panic("Verify returned invalid tag") } fmt.Printf("Sig%d tag: %s\n", i, hex.EncodeToString(tag[i])) // Verify the signature against the wrong message BAD := []byte("Goodbye world!") badtag, err := Verify(suite, BAD, Set(X), S, sig[i]) if err == nil || badtag != nil { panic("Signature verified against wrong message!?") } } if !bytes.Equal(tag[0], tag[1]) || !bytes.Equal(tag[2], tag[3]) || bytes.Equal(tag[0], tag[2]) { panic("tags aren't coming out right!") }
Output: Signature 0: 00000000 a2 f1 f3 e3 07 35 6c a9 16 fb 4f c9 a7 35 c7 3b |.....5l...O..5.;| 00000010 7f 09 8b 70 45 8d 5f c1 2b 74 22 f2 bf 3d d1 0a |...pE._.+t"..=..| 00000020 4b 8b 88 78 28 d6 5f 77 d0 d6 1b 26 47 cb 7a 2e |K..x(._w...&G.z.| 00000030 3c f8 8c 4b 8b 39 cd 3e 92 e1 2c 2d ac 7f db 01 |<..K.9.>..,-....| 00000040 1b 1d c2 e4 1d fd 54 b9 29 b9 f1 ec 9c e1 bc c8 |......T.).......| 00000050 b5 db c8 9f 71 1c 48 1c 2c 02 b2 14 de e7 b6 08 |....q.H.,.......| 00000060 61 f7 23 a0 e6 7c 95 b7 e4 b2 32 55 40 d4 25 87 |a.#..|....2U@.%.| 00000070 da d4 76 18 01 22 fb c7 93 f7 40 6b d6 e0 e7 0b |..v.."....@k....| 00000080 da 86 5d 31 13 21 f5 95 70 d8 d7 a1 26 3b 47 dd |..]1.!..p...&;G.| 00000090 60 5d c2 1d 38 bf b7 49 e9 47 4a 8d 89 a4 b0 89 |`]..8..I.GJ.....| Signature 1: 00000000 14 b6 dd a5 99 0c e7 f7 d5 82 43 d5 45 84 19 7b |..........C.E..{| 00000010 db c6 3b f5 ee ce 01 50 17 57 58 21 37 31 25 0d |..;....P.WX!71%.| 00000020 81 b1 81 c3 f3 00 f9 0f 9d 58 58 5f 66 f4 52 75 |.........XX_f.Ru| 00000030 0f bb bc fc 25 58 f7 29 74 8a 57 79 93 75 d9 0b |....%X.)t.Wy.u..| 00000040 11 3d 25 cb be 39 0f 88 2c f8 ee 63 93 d8 98 94 |.=%..9..,..c....| 00000050 1b 85 fd 38 0a 37 87 0b c1 db a7 53 50 72 98 0c |...8.7.....SPr..| 00000060 7f 9a fb 37 f7 64 66 5c 7c b5 1f 2d b1 d5 63 67 |...7.df\|..-..cg| 00000070 12 1b d4 18 0a 5b 42 b2 c0 9e 3a 42 e2 c2 77 0c |.....[B...:B..w.| 00000080 da 86 5d 31 13 21 f5 95 70 d8 d7 a1 26 3b 47 dd |..]1.!..p...&;G.| 00000090 60 5d c2 1d 38 bf b7 49 e9 47 4a 8d 89 a4 b0 89 |`]..8..I.GJ.....| Signature 2: 00000000 5f 11 1a 2f 10 28 55 d9 e2 be 10 56 7e 57 37 ae |_../.(U....V~W7.| 00000010 7a a1 bc ec 87 0f 98 4f 52 cc 70 e6 14 79 8a 01 |z......OR.p..y..| 00000020 89 f7 f8 b6 91 d1 52 f7 f0 b2 3d 3c 70 f1 95 9e |......R...=<p...| 00000030 2b 3b 76 1c d6 9e 2f 77 09 83 6a 7f 4d d8 4d 09 |+;v.../w..j.M.M.| 00000040 98 6f d5 7f 3b c0 00 e9 f7 80 0d ed 3c 15 b7 58 |.o..;.......<..X| 00000050 ba c2 c2 53 84 ff d0 6f 47 c3 b6 e6 24 66 19 00 |...S...oG...$f..| 00000060 9f a5 96 bf 08 a4 3f 2b bd 26 f2 0b 79 b9 92 c2 |......?+.&..y...| 00000070 00 6b f8 71 2a 95 60 07 92 4a 3b 86 c4 1b 98 0a |.k.q*.`..J;.....| 00000080 49 d9 9a 38 a8 da c4 44 3d 6b 56 70 78 9e f0 01 |I..8...D=kVpx...| 00000090 c6 da 3e d2 ff 20 b0 7c 0e 88 c6 52 a1 60 f5 6a |..>.. .|...R.`.j| Signature 3: 00000000 a9 0f 3b 86 6f 4e c6 ea 8d e8 57 2c 1a 20 c6 14 |..;.oN....W,. ..| 00000010 5e 5b 66 95 0b 41 ce 57 94 a1 f0 36 73 cd c8 04 |^[f..A.W...6s...| 00000020 ff 47 7b f3 6e ee 9e 1f bb 0d 96 e7 b8 50 1d 9f |.G{.n........P..| 00000030 8f bf ea bc ef f3 d5 d9 9b 05 9b d3 5e c9 41 0e |............^.A.| 00000040 d1 e8 a3 f6 7b b4 8e 38 db 73 4a ef ca 9a 68 7b |....{..8.sJ...h{| 00000050 c3 d0 2a e3 a9 e5 c1 a3 b7 bb 60 92 75 f1 7e 00 |..*.......`.u.~.| 00000060 9a bd 63 f7 c0 cf 2d a1 4d 1e 2c 40 ff 11 d6 4f |..c...-.M.,@...O| 00000070 c5 a2 70 ab 14 2e 11 ee 24 e6 ca ca 15 e2 f7 0f |..p.....$.......| 00000080 49 d9 9a 38 a8 da c4 44 3d 6b 56 70 78 9e f0 01 |I..8...D=kVpx...| 00000090 c6 da 3e d2 ff 20 b0 7c 0e 88 c6 52 a1 60 f5 6a |..>.. .|...R.`.j| Sig0 tag: da865d311321f59570d8d7a1263b47dd605dc21d38bfb749e9474a8d89a4b089 Sig1 tag: da865d311321f59570d8d7a1263b47dd605dc21d38bfb749e9474a8d89a4b089 Sig2 tag: 49d99a38a8dac4443d6b5670789ef001c6da3ed2ff20b07c0e88c652a160f56a Sig3 tag: 49d99a38a8dac4443d6b5670789ef001c6da3ed2ff20b07c0e88c652a160f56a
Example (One) ¶
This example demonstrates signing and signature verification using a trivial "anonymity set" of size 1, i.e., no anonymity. In this special case the signing scheme devolves to producing traditional ElGamal signatures: the resulting signatures are exactly the same length and represent essentially the same computational cost.
// Crypto setup: Get a suite which returns a predictable // random number stream for this example. // In production, simply use edwards25519.NewBlakeSHA256Ed25519() suite := edwards25519.NewBlakeSHA256Ed25519WithRand(blake2xb.New(nil)) // Create a public/private keypair (X[mine],x) X := make([]kyber.Point, 1) mine := 0 // which public key is mine x := suite.Scalar().Pick(suite.RandomStream()) // create a private key x X[mine] = suite.Point().Mul(x, nil) // corresponding public key X // Generate the signature M := []byte("Hello World!") // message we want to sign sig := Sign(suite, M, Set(X), nil, mine, x) fmt.Print("Signature:\n" + hex.Dump(sig)) // Verify the signature against the correct message tag, err := Verify(suite, M, Set(X), nil, sig) if err != nil { panic(err.Error()) } if tag == nil || len(tag) != 0 { panic("Verify returned wrong tag") } fmt.Println("Signature verified against correct message.") // Verify the signature against the wrong message BAD := []byte("Goodbye world!") tag, err = Verify(suite, BAD, Set(X), nil, sig) if err == nil || tag != nil { panic("Signature verified against wrong message!?") } fmt.Println("Verifying against wrong message: " + err.Error())
Output: Signature: 00000000 45 30 41 6a 51 d1 01 cf 7e ee 63 66 1d e9 e3 cf |E0AjQ...~.cf....| 00000010 a3 d2 1b 98 fc 46 99 6d 9f 91 cc 65 f4 9d 10 03 |.....F.m...e....| 00000020 45 a0 e0 5a bc fe 62 62 45 a9 e5 eb 00 e2 6b 66 |E..Z..bbE.....kf| 00000030 dc aa f0 53 7c 10 3e bf bd f6 30 8d 2d 2c 5c 0f |...S|.>...0.-,\.| Signature verified against correct message. Verifying against wrong message: invalid signature
func Verify ¶
func Verify(suite Suite, message []byte, anonymitySet Set, linkScope []byte, signatureBuffer []byte) ([]byte, error)
Verify checks a signature generated by Sign.
The caller provides the message, anonymity set, and linkage scope with which the signature was purportedly produced. If the signature is a valid linkable signature (linkScope != nil), this function returns a linkage tag that uniquely corresponds to the signer within the given linkScope. If the signature is a valid unlinkable signature (linkScope == nil), Verify returns an empty but non-nil byte-slice instead of a linkage tag on success. Returns a nil linkage tag and an error if the signature is invalid.