A ring signature, also know as a Spontaneous Anonymous Group (SAG) or 1outofn signature, convinces a verifier that a message is signed by any member in a group of n independent signers without allowing the verifier to identify who the signer was.
AbeOhkuboSuzuki Ring Signatures
In their paper, "1outofn Signatures from a Variety of Keys"[1], Abe, Ohkubo and Suzuki (AOS) present a method to construct a 1outofn signature scheme that allows mixture use of different flavours of keys at the same time.
Linkable Spontaneous Anonymous Group (LSAG) Signature
Liu, et al.[2] add the property of linkability to ring signatures. Linkability means
that two signatures by the same signer can be identified as such, but the signer remains anonymous. It adds the feature of claimability, which allows a signer to claim responsibility by providing proof of having generated a given signature.
A LSAG signature scheme satisfies three properties:
 Anonymity: A signer cannot be distinguished from a pool of
t
commitments (public keys).
 Spontaneity: No group secret, group manager of secret sharing setup stage.
 Linkability: Two signatures by the same signer can be linked.
A LSAG Signature Scheme over elliptic curves
It consists of two parts: signature generation and signature verification. Let L = {y_{0}, ..., y_{t1}} be a list of t
public keys. Let H:{0, 1}* > Z_{n} where H
is a cryptographic hash function and n
is the order of the elliptic curve over a finite field F_{q}. For i ∈ {0, ..., t1},
each user i
has a distinct public key y_{i} and a private key x_{i}.
Signature Generation
Let k ∈ {0, ..., t1} be the position of the prover's public key in the list L
of public keys. Let x_{k} be its private key. The LSAG signature of a message m ∈ {0,1}* is generated by the following steps:

Compute h = [H(L)] * g, where g
is the generator of the elliptic curve, and
y = [x_{k}] * h. Both computations are the product of a scalar and a point in the curve.

Select u ∈ Z_{n} and compute the first challenge ch_{k+1} = H(L, y, m, [u] * g, [u] * h)

For i in {k+1, ..., t1, 0, ... k1}, choose s_{i} ∈ Z_{n} and compute the remaining challenges: ch_{i+1} = H(L, y, m, [s_{i}] * g + [ch_{i}] * y_{i}, [s_{i}] * h + [ch_{i}] * y)

With the last ch_{k} computed, calculate s_{k} = (u  x_{k} * ch_{k}) mod n
The signature is (ch_{0}, [s_{0}, ..., s_{t1}], y).
Signature Verification
Given a message m
, a signature of a message (ch_{0}, [s_{0}, ..., s_{t1}], y) and a list of public keys L
, an honest verifier checks a signature as follows:

For i in {0, ..., t1} compute ch_{i+1} = H(L, y, m, [s_{i}] * g + [ch_{i}] * y_{i}, [s_{i}] * h + [ch_{i}] * y), where h = [H(L)] * g.

Check whether c_{0} is equal to H(L, y, m, [s_{t1}] * g + [ch_{t1}] * y_{t1}, [s_{t1}] * h + [ch_{t1}] * y)
testSignature
:: ECC.Curve
> Int
> ByteString
> IO Bool
testSignature curve nParticipants msg = do
 Generate public and private keys
(pubKey, privKey) < ECC.generate curve
 Generate random foreign participants
extPubKeys < genNPubKeys curve nParticipants
 Position of the signer's key in the set of public keys
k < fromInteger <$> generateBetween 0 (toInteger $ length extPubKeys  1)
 List of public keys
let pubKeys = insert k pubKey extPubKeys
 Sign message with list of public keys and signer's key pair
signature < sign pubKeys (pubKey, privKey) msg
 Verify signature
pure $ verify pubKeys signature msg
References:
 M. Abe, M. Ohkubo, K. Suzuki. "1outofn Signatures from a Variety of Keys", 2002
 K. Liu, K. Wei, S. Wong. "Linkable Spontaneous Anonymous Group
Signature for Ad Hoc Groups", 2004
Notation:
[b] * P
: multiplication of a point P and a scalar b over an elliptic curve defined over a finite field modulo a prime number
License
Copyright Adjoint Inc. (c) 2018
All rights reserved.