Documentation
¶
Overview ¶
Package anon implements cryptographic primitives for anonymous communication.
Index ¶
- func Decrypt(suite abstract.Suite, ciphertext []byte, anonymitySet Set, mine int, ...) ([]byte, error)
- func Encrypt(suite abstract.Suite, rand cipher.Stream, message []byte, anonymitySet Set, ...) []byte
- func Sign(suite abstract.Suite, random cipher.Stream, message []byte, anonymitySet Set, ...) []byte
- func Verify(suite abstract.Suite, message []byte, anonymitySet Set, linkScope []byte, ...) ([]byte, error)
- type PriKey
- type SKEME
- type Set
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Decrypt ¶
func Decrypt(suite abstract.Suite, ciphertext []byte, anonymitySet Set, mine int, privateKey abstract.Scalar, hide bool) ([]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 ¶
func Encrypt(suite abstract.Suite, rand cipher.Stream, message []byte, anonymitySet Set, hide bool) []byte
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.
If hide is true, Encrypt will produce a uniformly random-looking byte-stream, which reveals no metadata other than message length to anyone unable to decrypt the message. The provided abstract.Suite must support uniform-representation encoding of public keys for this to work.
Example (AnonSet) ¶
// Crypto setup suite := nist.NewAES128SHA256P256() rand := suite.Cipher([]byte("example")) // Create an anonymity set of random "public keys" X := make([]abstract.Point, 3) for i := range X { // pick random points X[i], _ = suite.Point().Pick(nil, rand) } // Make just one of them an actual public/private keypair (X[mine],x) mine := 1 // only the signer knows this x := suite.Scalar().Pick(rand) // create a private key x X[mine] = suite.Point().Mul(nil, x) // corresponding public key X // Encrypt a message with all the public keys M := []byte("Hello World!") // message to encrypt C := Encrypt(suite, rand, M, Set(X), false) 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, false) 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 04 a4 2a cf e6 41 38 3f d4 df 6e f4 70 05 a8 ec |..*..A8?..n.p...| 00000010 55 8a a5 a4 73 7f 34 ae 1c 50 69 fe af e4 71 01 |U...s.4..Pi...q.| 00000020 51 33 a7 89 e2 f0 85 81 ce e9 bc d2 49 cb aa 9a |Q3..........I...| 00000030 55 c5 99 ad 5c a5 e4 36 e4 71 c8 c1 58 4c f7 aa |U...\..6.q..XL..| 00000040 2f 3f d2 9a ec 4b fd 85 5e 1b 7f 08 3b 82 12 75 |/?...K..^...;..u| 00000050 76 e5 b2 0a 48 d1 d1 9a 5f 45 eb 57 e6 5b 4c 81 |v...H..._E.W.[L.| 00000060 10 d7 98 e0 f4 ce 98 9f 94 66 28 8d c4 ff 61 3f |.........f(...a?| 00000070 2a 61 c1 31 f8 b5 60 b7 82 05 64 e4 cd 86 66 43 |*a.1..`...d...fC| 00000080 f1 c1 de 23 d5 ea 19 ba dd 27 fa 4c 66 d8 a0 19 |...#.....'.Lf...| 00000090 1e 6c ea 70 b7 71 8f b5 cd 3a 49 6d c3 03 08 e0 |.l.p.q...:Im....| 000000a0 4d d6 67 9c 02 67 38 c2 d8 78 0d fd 97 f2 2b 8b |M.g..g8..x....+.| 000000b0 b3 b2 ae 0d f1 2b 1c 1b 13 9d 71 75 b8 |.....+....qu.| Decrypted: 'Hello World!'
func Sign ¶
func Sign(suite abstract.Suite, random cipher.Stream, message []byte, anonymitySet Set, linkScope []byte, mine int, privateKey abstract.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 Scalar" at http://people.csail.mit.edu/rivest/RivestShamirTauman-HowToLeakAScalar.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.
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 suite := nist.NewAES128SHA256P256() rand := suite.Cipher([]byte("example")) // Create an anonymity set of random "public keys" X := make([]abstract.Point, 3) for i := range X { // pick random points X[i], _ = suite.Point().Pick(nil, rand) } // Make just one of them an actual public/private keypair (X[mine],x) mine := 1 // only the signer knows this x := suite.Scalar().Pick(rand) // create a private key x X[mine] = suite.Point().Mul(nil, x) // corresponding public key X // Generate the signature M := []byte("Hello World!") // message we want to sign sig := Sign(suite, rand, 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 eb 16 0d c9 1e 19 f5 da f7 9b 77 7d 52 0b f1 82 |..........w}R...| 00000010 4b e3 dd 6c 44 f3 6f fe c3 c1 1a 6e 1f a8 43 26 |K..lD.o....n..C&| 00000020 63 d3 5a 0e 97 78 e6 74 ce a0 24 34 c1 66 7d af |c.Z..x.t..$4.f}.| 00000030 32 9e 59 22 f2 9a 67 3c ea e5 4f 54 6d 3e 07 f1 |2.Y"..g<..OTm>..| 00000040 63 10 77 96 09 a3 c1 e4 85 f8 d9 97 0c 47 dc 73 |c.w..........G.s| 00000050 da 6c d8 11 8a 2e 00 a7 f2 01 45 e0 91 4e 28 d6 |.l........E..N(.| 00000060 b2 b5 3a e1 c8 8c f7 29 8a 13 75 59 98 ea ce f4 |..:....)..uY....| 00000070 6d d5 d0 62 85 51 8e fe d9 4a 02 1f 35 03 33 d3 |m..b.Q...J..5.3.| 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 suite := nist.NewAES128SHA256P256() rand := suite.Cipher([]byte("example")) // Create an anonymity set of random "public keys" X := make([]abstract.Point, 3) for i := range X { // pick random points X[i], _ = suite.Point().Pick(nil, 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(nil, x1) // corresponding public key X X[mine2] = suite.Point().Mul(nil, x2) // 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, rand, M, Set(X), S, mine1, x1) sig[1] = Sign(suite, rand, M, Set(X), S, mine1, x1) sig[2] = Sign(suite, rand, M, Set(X), S, mine2, x2) sig[3] = Sign(suite, rand, 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 c6 e9 27 a5 00 5d 22 40 d2 a2 5d 08 44 2b ec 2e |..'..]"@..].D+..| 00000010 e2 01 a6 85 70 70 b4 73 2c 18 24 f1 46 44 22 09 |....pp.s,.$.FD".| 00000020 1e 6d 18 7f 8b 95 e3 c4 b9 33 ad 94 69 b5 b4 13 |.m.......3..i...| 00000030 b8 51 2f 24 a7 98 e4 06 f4 b2 f3 ee e8 73 de 78 |.Q/$.........s.x| 00000040 a3 9d 4b 1c 74 6f 3a 50 89 c9 10 cc bb b0 5c a7 |..K.to:P......\.| 00000050 09 a9 23 47 0f 36 08 a4 f3 46 ad 14 2d f0 9d c1 |..#G.6...F..-...| 00000060 63 d3 5a 0e 97 78 e6 74 ce a0 24 34 c1 66 7d af |c.Z..x.t..$4.f}.| 00000070 32 9e 59 22 f2 9a 67 3c ea e5 4f 54 6d 3e 07 f1 |2.Y"..g<..OTm>..| 00000080 04 00 33 42 ee 88 9f 5d fa 2e be 6a 72 fd 67 22 |..3B...]...jr.g"| 00000090 c1 e0 ed 35 69 d7 e4 67 df 92 e7 ca 75 2f e6 72 |...5i..g....u/.r| 000000a0 79 3a 32 e2 8b 45 61 e8 7d e5 95 5b 0a 30 35 e9 |y:2..Ea.}..[.05.| 000000b0 af 3c 41 48 59 d9 e2 73 68 77 31 f3 36 cc ee 78 |.<AHY..shw1.6..x| 000000c0 ab |.| Signature 1: 00000000 69 4c 29 32 cb 9c f6 ca 80 72 f6 25 e0 ef 44 0b |iL)2.....r.%..D.| 00000010 f2 0b e3 ab 98 c4 62 a3 10 13 09 02 9a f1 f1 00 |......b.........| 00000020 7f 03 ca 4f 75 84 fe 06 2c 9c 64 0e 99 c6 f1 91 |...Ou...,.d.....| 00000030 62 43 48 b6 f8 20 41 2b fa 59 e7 35 be f8 4c 1b |bCH.. A+.Y.5..L.| 00000040 f0 d8 af 83 ad 9a 87 55 ca be 46 f9 42 a2 dd 18 |.......U..F.B...| 00000050 18 83 f1 f5 6d 82 e5 38 49 bf 24 9e 80 a4 12 eb |....m..8I.$.....| 00000060 56 c5 3f 08 bb 99 6d 7d 0a f8 ac c5 29 e8 94 54 |V.?...m}....)..T| 00000070 3e 4d fb ca b5 1d 9a 29 56 a0 09 f9 ec 6d b5 28 |>M.....)V....m.(| 00000080 04 00 33 42 ee 88 9f 5d fa 2e be 6a 72 fd 67 22 |..3B...]...jr.g"| 00000090 c1 e0 ed 35 69 d7 e4 67 df 92 e7 ca 75 2f e6 72 |...5i..g....u/.r| 000000a0 79 3a 32 e2 8b 45 61 e8 7d e5 95 5b 0a 30 35 e9 |y:2..Ea.}..[.05.| 000000b0 af 3c 41 48 59 d9 e2 73 68 77 31 f3 36 cc ee 78 |.<AHY..shw1.6..x| 000000c0 ab |.| Signature 2: 00000000 94 d0 51 98 05 a1 79 6c 16 4e 7f f2 58 c8 09 b8 |..Q...yl.N..X...| 00000010 32 12 a5 dc be f3 cf 08 a8 77 8f 7e a7 32 dd 2b |2........w.~.2.+| 00000020 8b 48 7e 5a 4f eb 1d 1f c8 6c 96 e6 38 86 a9 50 |.H~ZO....l..8..P| 00000030 dc 69 e8 2d c9 ed 41 51 38 9d 5c 5f 9b e6 93 aa |.i.-..AQ8.\_....| 00000040 1c f7 7d 2f d1 ad 5c cd 4d ab 3a ed 2f 29 08 81 |..}/..\.M.:./)..| 00000050 55 61 40 8d 86 88 cd e6 62 be 28 b4 90 9c ae 69 |Ua@.....b.(....i| 00000060 54 1a 20 09 f3 84 ad 29 dc a8 64 cf c6 ec 92 f0 |T. ....)..d.....| 00000070 76 0f 36 28 66 88 81 2b 59 43 0c 69 6f f2 7a 8e |v.6(f..+YC.io.z.| 00000080 04 80 18 09 20 80 e9 9b 39 bc 17 47 55 13 8f c9 |.... ...9..GU...| 00000090 b4 9d 11 78 7b 56 0f f6 db 38 5f b4 f1 4f 3f 93 |...x{V...8_..O?.| 000000a0 63 9c 33 ea 86 f6 e1 54 79 c9 14 9f 45 b6 88 59 |c.3....Ty...E..Y| 000000b0 49 b6 76 99 c7 0c 84 6d 1a 9e 05 b0 30 c1 48 f2 |I.v....m....0.H.| 000000c0 9a |.| Signature 3: 00000000 1a 64 49 4a ff 66 bc 88 93 54 30 e9 96 89 34 76 |.dIJ.f...T0...4v| 00000010 f6 95 e0 a9 84 8a a2 6e f4 5e 7f db 58 d9 8a 48 |.......n.^..X..H| 00000020 84 bd 96 a9 6b 6e c2 47 03 9f 18 33 73 a5 2b ee |....kn.G...3s.+.| 00000030 11 e1 99 36 bf 44 42 26 5e f8 cc 25 1e 8a 97 2b |...6.DB&^..%...+| 00000040 7f 57 93 33 c5 fb 27 9f 24 e9 d4 3f 1c 16 67 4c |.W.3..'.$..?..gL| 00000050 50 0b d1 0b 08 9b 0f 3f cb ac 96 e8 92 3c a5 3d |P......?.....<.=| 00000060 d4 83 2c dd c6 6d e4 68 67 b7 dc 39 68 77 de 3d |..,..m.hg..9hw.=| 00000070 8c 83 0d b2 24 4b d6 17 e4 ce 78 7a 63 b7 f0 bb |....$K....xzc...| 00000080 04 80 18 09 20 80 e9 9b 39 bc 17 47 55 13 8f c9 |.... ...9..GU...| 00000090 b4 9d 11 78 7b 56 0f f6 db 38 5f b4 f1 4f 3f 93 |...x{V...8_..O?.| 000000a0 63 9c 33 ea 86 f6 e1 54 79 c9 14 9f 45 b6 88 59 |c.3....Ty...E..Y| 000000b0 49 b6 76 99 c7 0c 84 6d 1a 9e 05 b0 30 c1 48 f2 |I.v....m....0.H.| 000000c0 9a |.| Sig0 tag: 04003342ee889f5dfa2ebe6a72fd6722c1e0ed3569d7e467df92e7ca752fe672793a32e28b4561e87de5955b0a3035e9af3c414859d9e273687731f336ccee78ab Sig1 tag: 04003342ee889f5dfa2ebe6a72fd6722c1e0ed3569d7e467df92e7ca752fe672793a32e28b4561e87de5955b0a3035e9af3c414859d9e273687731f336ccee78ab Sig2 tag: 048018092080e99b39bc174755138fc9b49d11787b560ff6db385fb4f14f3f93639c33ea86f6e15479c9149f45b6885949b67699c70c846d1a9e05b030c148f29a Sig3 tag: 048018092080e99b39bc174755138fc9b49d11787b560ff6db385fb4f14f3f93639c33ea86f6e15479c9149f45b6885949b67699c70c846d1a9e05b030c148f29a
func Verify ¶
func Verify(suite abstract.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), 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.
Types ¶
type PriKey ¶
type PriKey struct { Set // Public key-set Mine int // Index of the public key I own Pri abstract.Scalar // Private key for that public key }
A private key representing a member of an anonymity set
type SKEME ¶
type SKEME struct {
// contains filtered or unexported fields
}
Pairwise anonymous key agreement for point-to-point interactions. We use the encryption-based SKEME authenticated key exchange protocol, with the anonymity-set encryption, to authenticate a Diffie-Hellman secret. The result is a private two-party communication channel, where each party knows that the other is a member of a specific set, but does not know the other's price identity unless his set is of size one. Once we have performed this key agreement, we can use more efficient pairwise cryptographic primitives such as GCM authenticators, which are not directly usable in multiparty contexts.