/// <summary> /// Represents a U-Prove token. /// </summary> /// <param name="uidp">The Issuer parameters UID.</param> /// <param name="h">The public key value h.</param> /// <param name="TI">The token information field value.</param> /// <param name="PI">The Prover information field value.</param> /// <param name="sigmaZPrime">The sigmaZPrime value.</param> /// <param name="sigmaCPrime">The sigmaCPrime value.</param> /// <param name="sigmaRPrime">The sigmaRPrime value.</param> /// <param name="isDeviceProtected">True if the token is Device-protected, false otherwise.</param> public UProveToken(byte[] uidp, GroupElement h, byte[] TI, byte[] PI, GroupElement sigmaZPrime, FieldZqElement sigmaCPrime, FieldZqElement sigmaRPrime, bool isDeviceProtected) { this.uidp = uidp; this.h = h; this.ti = TI; this.pi = PI; this.sigmaZPrime = sigmaZPrime; this.sigmaCPrime = sigmaCPrime; this.sigmaRPrime = sigmaRPrime; this.isDeviceProtected = isDeviceProtected; }
/// <summary> /// Private constructor - takes and sets all fields. /// </summary> /// <param name="Gq">The group</param> /// <param name="gd">The device generator</param> /// <param name="Zq">The Field associated to the group <c>Gq</c></param> /// <param name="xd">The xd.</param> /// <param name="preGenWdPrime">The pre gen wd prime.</param> VirtualDevice(Group Gq, GroupElement gd, FieldZq Zq, FieldZqElement xd, FieldZqElement preGenWdPrime) { if (xd != null && !Zq.IsElement(xd)) { throw new ArgumentException("xd is not a valid Zq element"); } this.Gd = gd; this.Gq = Gq; this.Zq = Zq; this.xd = xd ?? this.Zq.GetRandomElement(true); // assign xd a random value if null this.wdPrime = preGenWdPrime; this.hd = this.Gd.Exponentiate(this.xd); }
/// <summary> /// Generates the Issuer parameters cryptographic data, <code>ip</code> will be updated with the cryptographic data. /// </summary> /// <param name="ip">An instanciated Issuer parameters; the Gq and E properties must be set.</param> /// <param name="gValues">The issuer generators to use, or null.</param> /// <param name="supportDevice">Indicates if the device generator must be generated.</param> /// <returns>The Issuer parameters private key.</returns> internal static FieldZqElement GenerateIssuerParametersCryptoData(IssuerParameters ip, GroupElement[] gValues, bool supportDevice) { if (ip == null) { throw new ArgumentNullException("ip"); } if (ip.Gq == null) { throw new ArgumentException("Group description is not set"); } int n = ip.E == null ? 0 : ip.E.Length; Group Gq = ip.Gq; ip.G = new GroupElement[n + 2]; FieldZqElement privateKey; if (gValues == null) { FieldZqElement[] y = ip.Zq.GetRandomElements(n + 2, false); privateKey = y[0]; for (int i = 0; i < (n + 2); i++) { ip.G[i] = Gq.G.Exponentiate(y[i]); } } else { // g_0 privateKey = ip.Zq.GetRandomElement(false); ip.G[0] = Gq.G.Exponentiate(privateKey); // g_1,..,g_n for (int i = 1; i < (n + 1); i++) { ip.G[i] = gValues[i - 1]; } // g_t int t = n + 1; ip.G[t] = gValues[gValues.Length - 1]; } if (supportDevice) { if (ip.Gd == null) { ip.Gd = Gq.G.Exponentiate(ip.Zq.GetRandomElement(false)); } } return privateKey; }
/// <summary> /// Generates an array of random group elements. Calls GetRandomElement n times. /// </summary> /// <param name="n">The number of elements to return.</param> /// <param name="nonIdentity">True to return non-identity elements.</param> /// <param name="maxBitLength">Maximum length of the exponent used to get random element. For example, to choose a random /// group elements from the set {G^0, G^1, G^2, G^3}, set maxBitLength to 2. Set maxBitLength to -1 to choose random group elements /// from the entire group.</param> /// <returns>Random group elements.</returns> public GroupElement[] GetRandomElements(int n, bool nonIdentity, int maxBitLength = -1) { if (maxBitLength != -1) { throw new NotImplementedException("GetRandomElement cannot handle argument maxBitLength != -1."); } GroupElement[] r = new GroupElement[n]; for (int i = 0; i < n; i++) { r[i] = GetRandomElement(nonIdentity, maxBitLength); } return(r); }
/// <summary> /// Generates the U-Prove key and tokens. /// </summary> /// <param name="message">The third issuance message.</param> /// <param name="skipTokenValidation">Set to <code>true</code> to skip token validation; /// <code>false</code> otherwise. Token validation SHOULD be performed before use, either /// by setting <code>skipTokenValidation</code> to <code>false</code>, or by later using the /// <code>ProtocolHelper.VerifyTokenSignature</code> method. /// </param> /// <exception cref="InvalidUProveArtifactException">If the token signature is invalid.</exception> /// <returns>An array of U-Prove keys and tokens</returns> public UProveKeyAndToken[] GenerateTokens(ThirdIssuanceMessage message, bool skipTokenValidation = false) { if (state != State.Second) { throw new InvalidOperationException("GenerateSecondMessage must be called first"); } bool doBatchValidation = !skipTokenValidation && batchValidationSecurityLevel > 0; bool doNormalValidation = !skipTokenValidation && batchValidationSecurityLevel <= 0; Group Gq = ip.Gq; FieldZq Zq = ip.Zq; FieldZqElement[] sigmaRPrime = new FieldZqElement[numberOfTokens]; FieldZqElement phoAR = Zq.Zero, phoR = Zq.Zero, phoAC = Zq.Zero, phoC = Zq.Zero; GroupElement batchAcc = Gq.Identity; for (int i = 0; i < numberOfTokens; i++) { sigmaRPrime[i] = message.sigmaR[i] + beta2[i]; if (doBatchValidation) { FieldZqElement s = Zq.GetRandomElement(true, batchValidationSecurityLevel); phoAR += (s * alpha[i] * sigmaRPrime[i]); phoR += (s * sigmaRPrime[i]); phoAC += (s * alpha[i] * sigmaCPrime[i]); phoC += (s * sigmaCPrime[i]); batchAcc *= (sigmaAPrime[i] * sigmaBPrime[i]).Exponentiate(s); } else if (doNormalValidation) { if (!(sigmaAPrime[i] * sigmaBPrime[i]).Equals( ((Gq.G * h[i]).Exponentiate(sigmaRPrime[i]) * (ip.G[0] * sigmaZPrime[i]).Exponentiate(sigmaCPrime[i].Negate())))) { throw new InvalidUProveArtifactException("Invalid token signature: " + i); } } ukat[i].Token = new UProveToken(ip.UidP, h[i], TI, PI, sigmaZPrime[i], sigmaCPrime[i], sigmaRPrime[i], isDeviceProtected); } if (doBatchValidation && (batchAcc != Gq.G.Exponentiate(phoR) * gamma.Exponentiate(phoAR) * ip.G[0].Exponentiate(phoC.Negate()) * sigmaZ.Exponentiate(phoAC.Negate()))) { throw new InvalidUProveArtifactException("Invalid token signature"); } state = State.Tokens; return(ukat); }
/// <summary> /// Constructs an Issuer parameters instance from a serialized string /// </summary> public IssuerParameters(string serializedIssuerParameters) { IssuerParameters.serializer = new Serializer(); IssuerParameters issuerParameters = this.Deserialize <IssuerParameters>(serializedIssuerParameters); this.uidp = issuerParameters.uidp; this.group = issuerParameters.group; this.uidh = issuerParameters.uidh; this.g = issuerParameters.g; this.gd = issuerParameters.gd; this.e = issuerParameters.e; this.s = issuerParameters.s; this.usesRecommendedParameters = issuerParameters.usesRecommendedParameters; }
/// <summary> /// Constructs an Issuer parameters instance. /// </summary> /// <param name="uidp">The Issuer parameters UID.</param> /// <param name="group">The group description.</param> /// <param name="uidh">The hash algorithm identifier.</param> /// <param name="g">The generator values.</param> /// <param name="gd">The Device generator, or null.</param> /// <param name="e">The encoding bytes.</param> /// <param name="s">The specification bytes.</param> /// <param name="usesRecommendedParameters">Indicates if the group and g array uses the recommended parameters.</param> /// <param name="maxNumberOfAttributes">maximum number of attributes, the issuer will be able to include into an issued token - extension by Fablei</param> public IssuerParameters(byte[] uidp, Group group, string uidh, GroupElement[] g, GroupElement gd, byte[] e, byte[] s, bool usesRecommendedParameters, int maxNumberOfAttributes) { this.uidp = uidp; this.group = group; this.uidh = uidh; this.g = g; this.gd = gd; this.e = e; this.s = s; this.usesRecommendedParameters = usesRecommendedParameters; // extension by Fablei MaxNumberOfAttributes = maxNumberOfAttributes; IssuerParameters.serializer = new Serializer(); }
public static FirstIssuanceMessage convertFirstIssuanceMessageComposite(FirstIssuanceMessageComposite fic, IssuerParameters ip) { GroupElement[] geArray1 = new GroupElement[fic.SigmaA.Length]; for (int i = 0; i < fic.SigmaA.Length; i++) { geArray1[i] = ip.Gq.CreateGroupElement(fic.SigmaA[i]); } GroupElement[] geArray2 = new GroupElement[fic.SigmaB.Length]; for (int i = 0; i < fic.SigmaB.Length; i++) { geArray2[i] = ip.Gq.CreateGroupElement(fic.SigmaB[i]); } FirstIssuanceMessage fi = new FirstIssuanceMessage(ip.Gq.CreateGroupElement(fic.SigmaZ), geArray1, geArray2); return fi; }
/// <summary> /// Convert a base64 string to a GroupElement[] using a specific Group object. /// </summary> /// <param name="encodedElements">The encoded string to convert.</param> /// <param name="group">The group object to use.</param> /// <returns>The converted object.</returns> public static GroupElement[] ToGroupElementArray(this String[] encodedElements, Group group) { if (encodedElements == null) { return(null); } if (group == null) { throw new ArgumentNullException("group"); } GroupElement[] groupElements = new GroupElement[encodedElements.Length]; for (int i = 0; i < encodedElements.Length; i++) { groupElements[i] = encodedElements[i].ToGroupElement(group); } return(groupElements); }
/// <summary> /// Constructs an Issuer parameters instance from a serialized string /// </summary> public IssuerParameters(string serializedIssuerParameters) { IssuerParameters.serializer = new Serializer(); IssuerParameters issuerParameters = this.Deserialize <IssuerParameters>(serializedIssuerParameters); this.uidp = issuerParameters.uidp; this.group = issuerParameters.group; this.uidh = issuerParameters.uidh; this.g = issuerParameters.g; this.gd = issuerParameters.gd; this.e = issuerParameters.e; this.s = issuerParameters.s; this.usesRecommendedParameters = issuerParameters.usesRecommendedParameters; // extension by Fablei MaxNumberOfAttributes = issuerParameters.MaxNumberOfAttributes; }
/// <summary> /// Computes the value <c>gamma</c>, an input to the issuance protocol. /// </summary> /// <param name="ip">The issuer parameters</param> /// <param name="A"> The attribute values, or null if the token contains no attributes </param> /// <param name="TI">The token information field</param> /// <param name="hd">The device public key, or <c>null</c> if device binding is not supported by the issuer paramters.</param> /// <returns>The group element gamma </returns> public static GroupElement ComputeIssuanceInput(IssuerParameters ip, byte[][] A, byte[] TI, GroupElement hd) { if (ip == null) { throw new ArgumentNullException("Issuer parameters are null"); } int n = 0; bool supportDevice = (hd != null); if (supportDevice && !ip.IsDeviceSupported) { throw new InvalidOperationException("Issuer parameters does not support devices"); } if (A != null) { n = A.Length; } Group Gq = ip.Gq; GroupElement[] bases = new GroupElement[n + 1]; FieldZqElement[] exponents = new FieldZqElement[n + 1]; for (int i = 0; i < n; i++) { FieldZqElement xi = ComputeXi(ip, i, A[i]); bases[i] = ip.G[i + 1]; exponents[i] = xi; } FieldZqElement xt = ComputeXt(ip, TI, supportDevice); bases[n] = ip.G[n + 1]; exponents[n] = xt; GroupElement gamma = ip.G[0] * Gq.MultiExponentiate(bases, exponents); // Multiply-in the device public key for device-protected tokens if (supportDevice) { gamma = gamma * hd; } return(gamma); }
GroupElement IDevicePresentationContext.GetInitialWitnessesAndPseudonym(GroupElement gs, out GroupElement apPrime, out GroupElement Ps) { if (this.device == null) { throw new DeviceException("Invalid context."); } if (this.wdPrime != null) { throw new DeviceException("Initial witness already calculated."); } this.wdPrime = this.device.wdPrime ?? this.device.Zq.GetRandomElement(false); // compute pseudonym apPrime = gs.Exponentiate(this.wdPrime); Ps = gs.Exponentiate(this.device.xd); // compute initial witness return(this.device.Gd.Exponentiate(this.wdPrime)); }
/// <summary> /// Constructs a new SampleDevice instance. /// </summary> /// <param name="gq">The group construction.</param> /// <param name="gd">The device generator.</param> public SmartCardDevice(GroupDescription gq, GroupElement gd, SmartCardParams smartCardParam) { pin = smartCardParam.pin; credID = smartCardParam.credID; groupID = smartCardParam.groupID; proverID = smartCardParam.proverID; // As SnartCardDevice do not provide a way to lookup card readr names // we provide a small potion of logic to lookup a card and cardreader List<CardInfo> cardInfoList = SmartCardUtils.GetReaderNames(); // loop until we find a card with the status of "working mode". if none found // throw String readerName = null; foreach (CardInfo i in cardInfoList) { if (i.CardMode == (int)CardMode.WORKING) { readerName = i.ReaderName; break; } } if (readerName == null) { // TODO create a better exception throw new Exception("No card founds in working mode"); } bool doTimeProfile = ParseConfigManager.doTimeProfile(); this.device = new SmartCard(readerName, pin, doTimeProfile); // As the group and generator is set from the java init service we will only verify // TODO fix to see that group 0 is set on the hw smartcard. //if (!this.device.IsGeneratorSet(groupID)) //{ // TODO Find better exception // throw new Exception("No generator is set on the card to use this group"); //} this.Gq = gq; this.Gd = gd; }
private byte[] ComputeDigest(bool deviceProtected) { HashFunction H = this.HashFunction; H.Hash(UidP); H.Hash(group); if (deviceProtected) { // Gd must be part of the Gi array GroupElement[] GWithGd = new GroupElement[G.Length + 1]; Array.Copy(G, GWithGd, G.Length); GWithGd[G.Length] = gd; H.Hash(GWithGd); } else { H.Hash(G); } H.Hash(E); H.Hash(S); return(H.Digest); }
void IParametrizedDeserialization.FinishDeserialization(IssuerParameters ip) { try { if (!this.deserializationStarted) { throw new SerializationException("deserialization not started"); } this.h = _h.ToGroupElement(ip); this.sigmaZPrime = _sigmaZPrime.ToGroupElement(ip); this.sigmaCPrime = _sigmaCPrime.ToFieldZqElement(ip.Zq); this.sigmaRPrime = _sigmaRPrime.ToFieldZqElement(ip.Zq); } catch { throw; } finally { this.deserializationStarted = false; } }
internal void OnDeserialized(StreamingContext context) { if (_uidp == null) { throw new UProveSerializationException("uidp"); } if (_h == null) { throw new UProveSerializationException("h"); } if (_sigmaZPrime == null) { throw new UProveSerializationException("szp"); } if (_sigmaCPrime == null) { throw new UProveSerializationException("scp"); } if (_sigmaRPrime == null) { throw new UProveSerializationException("srp"); } // default to false if not provided if (_isDeviceProtected == null) { _isDeviceProtected = false; } this.uidp = _uidp.ToByteArray(); this.h = _h.ToGroupElement(Serializer.ip); this.ti = _ti.ToByteArray(); this.pi = _pi.ToByteArray(); this.sigmaZPrime = _sigmaZPrime.ToGroupElement(Serializer.ip); this.sigmaCPrime = _sigmaCPrime.ToFieldZqElement(Serializer.ip.Zq); this.sigmaRPrime = _sigmaRPrime.ToFieldZqElement(Serializer.ip.Zq); this.isDeviceProtected = _isDeviceProtected.Value; }
/// <summary> /// Returns the product of all the numerators divided by the product of all the denominators. /// </summary> /// <param name="numerators">Array of group elements to multiply together to form the numerator.</param> /// <param name="denominators">Array of group elements to multiply together to form the denominator.</param> /// <returns>Quotient.</returns> public GroupElement Divide(GroupElement[] numerators, GroupElement[] denominators) { if ((numerators == null) || (denominators == null)) { throw new ArgumentNullException("Divide expects all arguments to be not null."); } GroupElement numerator = this.Identity; for (int i = 0; i < numerators.Length; ++i) { numerator *= numerators[i]; } GroupElement denominator = this.Identity; for (int i = 0; i < denominators.Length; ++i) { denominator *= denominators[i]; } return(this.Divide(numerator, denominator)); }
/// <summary> /// Constructs a new <code>Prover</code> instance. /// </summary> /// <param name="ip">The Issuer parameters.</param> /// <param name="numberOfTokens">Number of tokens to issue.</param> /// <param name="gamma">The gamma value encoding the token attributes. If <c>beta0</c> is non-null, then this value is blinded with <c>beta0</c>.</param> /// <param name="TI">The token information field value.</param> /// <param name="PI">The Prover information field value.</param> /// <param name="preGeneratedRandomData">Optional pregenerated ProverRandomData instance.</param> /// <param name="isDeviceProtected">True if the token is to be device-protected, false otherwise.</param> /// <param name="batchValidationSecurityLevel">The security level of the batch token signature validation. Given a security level <code>l</code>, /// the probability for the Prover to accept an invalid token is <code>2^-l</code>. If set to 0, than /// regular validation is used. A value of 20 is recommended.</param> /// <param name="beta0">Non-null if the input <c>gamma</c> value is blinded (collaborative issuance, i.e., the input <c>gamma</c> is blinded with beta0). /// This parameter defaults to null if ommitted. </param> internal Prover(IssuerParameters ip, int numberOfTokens, GroupElement gamma, byte[] TI, byte[] PI, ProverRandomData preGeneratedRandomData, bool isDeviceProtected, ushort batchValidationSecurityLevel, FieldZqElement beta0 = null) { if (ip == null) { throw new ArgumentNullException("ip"); } this.ip = ip; if (numberOfTokens <= 0) { throw new ArgumentException("numberOfTokens must be greater than 0"); } this.numberOfTokens = numberOfTokens; this.TI = TI; this.PI = PI; if (preGeneratedRandomData != null && (preGeneratedRandomData.Alpha.Length != numberOfTokens || preGeneratedRandomData.Beta1.Length != numberOfTokens || preGeneratedRandomData.Beta2.Length != numberOfTokens)) { throw new ArgumentException("invalid preGeneratedRandomData"); } this.isDeviceProtected = isDeviceProtected; this.batchValidationSecurityLevel = batchValidationSecurityLevel; this.gamma = gamma; if (beta0 != null) // inputs are blinded; collab issuance { this.beta0Inverse = beta0.Invert(); } else // no collab issuance { this.beta0Inverse = ip.Zq.One; } Precompute(gamma, preGeneratedRandomData); }
public void Verify(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, UProveToken upt) { try { // make sure disclosed list is sorted if (disclosed == null) { // can't be null later, so make it an empty array disclosed = new int[] { }; } Array.Sort(disclosed); Group Gq = ip.Gq; int n = ip.E.Length; bool presentPseudonym = false; if (gs != null && pseudonymAttribIndex != 0) { if (pseudonymAttribIndex < 1 || (pseudonymAttribIndex > n && pseudonymAttribIndex != DeviceAttributeIndex)) { throw new ArgumentException("pseudonymAttribIndex must be between 1 and " + n + " (inclusive)"); } if (disclosed.Contains(pseudonymAttribIndex)) { throw new ArgumentException("pseudonymAttribIndex cannot be in the disclosed attribute array"); } presentPseudonym = true; } else // no nym { pseudonymAttribIndex = 0; } bool verifyCommitments = (committed != null && committed.Length > 0); if (verifyCommitments) { Array.Sort(committed); } ProtocolHelper.VerifyTokenSignature(ip, upt); FieldZqElement[] disclosedX = new FieldZqElement[disclosedAttributes.Length]; GroupElement dAccumulator = ip.G[0] * ip.G[n + 1].Exponentiate(ProtocolHelper.ComputeXt(ip, upt.TI, upt.IsDeviceProtected)); // g0 * gt^xt GroupElement uAccumulator = upt.H.Exponentiate(this.r[0]); int dIndex = 0; int uIndex = 1; int cIndex = 0; int pseudonymResponseIndex = 0; int[] commitmentResponseIndices = verifyCommitments ? new int[committed.Length] : null; for (int i = 1; i <= n; i++) { if (disclosed.Contains(i)) { disclosedX[dIndex] = ProtocolHelper.ComputeXi(ip, i - 1, disclosedAttributes[dIndex]); dAccumulator = dAccumulator * ip.G[i].Exponentiate(disclosedX[dIndex]); dIndex++; } else { uAccumulator = uAccumulator * ip.G[i].Exponentiate(this.r[uIndex]); if (presentPseudonym) { if (pseudonymAttribIndex == i) { pseudonymResponseIndex = uIndex; } } if (verifyCommitments) { if (committed.Contains(i)) { // remember which response correspond to which commitment commitmentResponseIndices[cIndex] = uIndex; cIndex++; } } uIndex++; } } if (pseudonymAttribIndex == DeviceAttributeIndex) { pseudonymResponseIndex = this.r.Length - 1; // r_d is the last response in the array } byte[] unused; // verifier doesn't use the returned message for device FieldZqElement c = ProtocolHelper.GenerateChallenge(ip, upt, this.a, pseudonymAttribIndex, this.ap, this.ps, message, messageD, disclosed, disclosedX, committed, this.Commitments, out unused); HashFunction hash = ip.HashFunction; hash.Hash((dAccumulator.Exponentiate(c.Negate()) * uAccumulator * (upt.IsDeviceProtected ? ip.Gd.Exponentiate(this.r[this.r.Length -1]) : Gq.Identity))); if (!this.a.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } if (presentPseudonym) { hash.Hash(this.ps.Exponentiate(c).Multiply(gs.Exponentiate(this.r[pseudonymResponseIndex]))); if (!this.ap.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid pseudonym"); } } if (verifyCommitments) { for (int i = 0; i < commitmentResponseIndices.Length; i++) { CommitmentValues commitment = this.Commitments[i]; hash.Hash(commitment.TildeC.Exponentiate(c).Multiply(ip.Gq.G.Exponentiate(this.r[commitmentResponseIndices[i]])).Multiply(ip.G[1].Exponentiate(commitment.TildeR))); if (!commitment.TildeA.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid commitment " + committed[i]); } } } } catch (ArgumentException) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } catch (IndexOutOfRangeException) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } }
/// <summary> /// Constructs a new instance. /// </summary> /// <param name="tildeC">The <code>tildeC</code> value.</param> /// <param name="tildeA">The <code>tildeA</code> value.</param> /// <param name="tildeR">The <code>tildeR</code> value.</param> public CommitmentValues(GroupElement tildeC, byte[] tildeA, FieldZqElement tildeR) { TildeC = tildeC; TildeA = tildeA; TildeR = tildeR; }
/// <summary> /// Generates a presentation proof including optionally presenting a pseudonym, creating attribute commitments, and passing pre-generated random values. /// </summary> /// <param name="ip">The issuer parameters corresponding to <code>upkt</code>.</param> /// <param name="disclosed">An ordered array of disclosed attribute indices.</param> /// <param name="committed">An ordered array of committed attribute indices.</param> /// <param name="pseudonymAttribIndex">Index of the attribute used to create a scope-exclusive pseudonym, or 0 if no pseudonym is to be presented. The index must not be part of the disclosed attributes.</param> /// <param name="gs">The pseudonym scope element, or null if no pseudonym is to be presented.</param> /// <param name="message">The presentation message.</param> /// <param name="messageD">The message for the Device, or null.</param> /// <param name="deviceContext">The active device context, if token is device-protected, or null.</param> /// <param name="upkt">The U-Proke key and token.</param> /// <param name="attributes">The token attributes.</param> /// <param name="preGenW">Optional pregenerated random data for the proof generation.</param> /// <param name="cpv">Returned commitment private values if commitments are computed.</param> /// <returns>A presentation proof.</returns> internal static PresentationProof Generate(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, IDevicePresentationContext deviceContext, UProveKeyAndToken upkt, byte[][] attributes, ProofGenerationRandomData preGenW, out CommitmentPrivateValues cpv) { if (upkt.Token.IsDeviceProtected && deviceContext == null) { throw new ArgumentNullException("Device context is not initialized"); } bool generateCommitments = (committed != null && committed.Length > 0); FieldZqElement[] tildeO = null; // make sure disclosed and committed lists are sorted if (disclosed == null) { // can't be null later, so make it an empty array disclosed = new int[] { }; } Array.Sort(disclosed); if (generateCommitments) { Array.Sort(committed); } int n = 0; if (ip.E != null) n = ip.E.Length; bool presentPseudonym = false; if (gs != null) { if (pseudonymAttribIndex < 1 || (pseudonymAttribIndex > n && pseudonymAttribIndex != DeviceAttributeIndex)) { throw new ArgumentException("pseudonymAttribIndex must be between 1 and " + n + " (inclusive)"); } if (disclosed.Contains(pseudonymAttribIndex)) { throw new ArgumentException("pseudonymAttribIndex cannot be in the disclosed attribute array"); } presentPseudonym = true; } else if (pseudonymAttribIndex > 0) { throw new ArgumentNullException("gs is null"); } else { pseudonymAttribIndex = 0; } Group Gq = ip.Gq; FieldZq Zq = ip.Zq; FieldZqElement xt = ProtocolHelper.ComputeXt(ip, upkt.Token.TI, upkt.Token.IsDeviceProtected); ProofGenerationRandomData random; if (preGenW == null) { random = ProofGenerationRandomData.Generate(n - disclosed.Length, generateCommitments ? committed.Length : 0, Zq, upkt.Token.IsDeviceProtected); } else { random = preGenW; } FieldZqElement[] x = new FieldZqElement[n]; GroupElement temp = upkt.Token.H.Exponentiate(random.W0); int uIndex = 0; int dIndex = 0; int cIndex = 0; PresentationProof proof = new PresentationProof(); proof.DisclosedAttributes = new byte[disclosed.Length][]; int pseudonymRandomizerIndex = 0; if (generateCommitments) { proof.Commitments = new CommitmentValues[committed.Length]; tildeO = new FieldZqElement[committed.Length]; } HashFunction hash = ip.HashFunction; for (int i = 0; i < n; i++) { x[i] = ProtocolHelper.ComputeXi(ip, i, attributes[i]); if (!disclosed.Contains(i + 1)) { temp = temp * ip.G[i + 1].Exponentiate(random.W[uIndex]); if (presentPseudonym) { if (pseudonymAttribIndex == (i + 1)) { pseudonymRandomizerIndex = uIndex; } } if (generateCommitments && committed.Contains(i + 1)) { GroupElement tildeC = ip.Gq.G.Exponentiate(x[i]) * ip.G[1].Exponentiate(random.TildeO[cIndex]); tildeO[cIndex] = random.TildeO[cIndex]; GroupElement temp2 = ip.Gq.G.Exponentiate(random.W[uIndex]) * ip.G[1].Exponentiate(random.TildeW[cIndex]); hash.Hash(temp2); byte[] tildeA = hash.Digest; proof.Commitments[cIndex] = new CommitmentValues(tildeC, tildeA, null); cIndex++; } uIndex++; } else if (generateCommitments && committed.Contains(i + 1)) { throw new ArgumentException("attribute " + (i + 1) + " cannot be both disclosed and committed"); } else { proof.DisclosedAttributes[dIndex] = attributes[i]; dIndex++; } } if (upkt.Token.IsDeviceProtected) { GroupElement ad; // pseudonym computed by device if (presentPseudonym && pseudonymAttribIndex == DeviceAttributeIndex) { GroupElement apPrime; GroupElement Ps; ad = deviceContext.GetInitialWitnessesAndPseudonym(gs, out apPrime, out Ps); hash.Hash(apPrime * gs.Exponentiate(random.Wd)); proof.Ap = hash.Digest; proof.Ps = Ps; } else { ad = deviceContext.GetInitialWitness(); } temp = temp * ip.Gd.Exponentiate(random.Wd) * ad; } hash.Hash(temp); proof.a = hash.Digest; // pseudonym derived from one token attribute if (presentPseudonym && pseudonymAttribIndex != DeviceAttributeIndex) { hash.Hash(gs.Exponentiate(random.W[pseudonymRandomizerIndex])); proof.Ap = hash.Digest; proof.Ps = gs.Exponentiate(x[pseudonymAttribIndex - 1]); } byte[] mdPrime; FieldZqElement c = ProtocolHelper.GenerateChallenge(ip, upkt.Token, proof.a, pseudonymAttribIndex, proof.ap, proof.Ps, message, messageD, disclosed, GetDisclosedX(disclosed, x), committed, proof.Commitments, out mdPrime); proof.r = new FieldZqElement[1 + n - disclosed.Length + (upkt.Token.IsDeviceProtected ? 1 : 0)]; // r_0, {r_i} for undisclosed i, r_d proof.r[0] = c * upkt.PrivateKey + random.W0; uIndex = 1; for (int i = 1; i <= n; i++) { if (!disclosed.Contains(i)) { proof.r[uIndex] = c.Negate() * x[i - 1] + random.W[uIndex - 1]; uIndex++; } } if (upkt.Token.IsDeviceProtected) { proof.r[proof.r.Length - 1] = deviceContext.GetDeviceResponse(messageD, mdPrime, ip.HashFunctionOID) + random.Wd; } if (generateCommitments) { for (int i = 0; i < committed.Length; i++) { proof.Commitments[i].TildeR = c.Negate() * random.TildeO[i] + random.TildeW[i]; } } random.Clear(); cpv = new CommitmentPrivateValues(tildeO); return proof; }
/// <summary> /// Create a first issuance message. Notation defined in the U-Prove spec. /// </summary> public FirstIssuanceMessage(GroupElement sigmaZ, GroupElement[] sigmaA, GroupElement[] sigmaB) { this.sigmaA = sigmaA; this.sigmaB = sigmaB; this.sigmaZ = sigmaZ; }
GroupElement IDevicePresentationContext.GetInitialWitnessesAndPseudonym(GroupElement gs, out GroupElement apPrime, out GroupElement Ps) { if (this.device == null) { throw new DeviceException("Invalid context."); } if (this.wdPrime != null) { throw new DeviceException("Initial witness already calculated."); } this.wdPrime = this.device.wdPrime ?? this.device.Zq.GetRandomElement(false); // compute pseudonym apPrime = gs.Exponentiate(this.wdPrime); Ps = gs.Exponentiate(this.device.xd); // compute initial witness return this.device.Gd.Exponentiate(this.wdPrime); }
/// <summary> /// Constructs a new <code>Issuer</code> instance. /// </summary> /// <param name="ikap">The Issuer key and parameters.</param> /// <param name="numberOfTokens">Number of tokens to issue.</param> /// <param name="gamma">The gamma value encoding the token attributes.</param> /// <param name="preGeneratedW">Optional pregenerated <code>numberOfTokens</code> random Zq elements.</param> internal Issuer(IssuerKeyAndParameters ikap, int numberOfTokens, GroupElement gamma, FieldZqElement[] preGeneratedW) { if (ikap == null || ikap.PrivateKey == null || ikap.IssuerParameters == null) { throw new ArgumentNullException("ikap is malformed or null"); } this.ikap = ikap; if (numberOfTokens <= 0) { throw new ArgumentException("numberOfTokens must be greater than 0"); } this.numberOfTokens = numberOfTokens; if (gamma == null) { throw new ArgumentNullException("gamma is null"); } if (preGeneratedW != null && preGeneratedW.Length != numberOfTokens) { throw new ArgumentException("invalid preGeneratedW array length"); } Precompute(gamma, preGeneratedW); }
public void Verify(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, UProveToken upt) { try { // make sure disclosed list is sorted if (disclosed == null) { // can't be null later, so make it an empty array disclosed = new int[] { }; } Array.Sort(disclosed); Group Gq = ip.Gq; int n = ip.E.Length; bool presentPseudonym = false; if (gs != null && pseudonymAttribIndex != 0) { if (pseudonymAttribIndex < 1 || (pseudonymAttribIndex > n && pseudonymAttribIndex != DeviceAttributeIndex)) { throw new ArgumentException("pseudonymAttribIndex must be between 1 and " + n + " (inclusive)"); } if (disclosed.Contains(pseudonymAttribIndex)) { throw new ArgumentException("pseudonymAttribIndex cannot be in the disclosed attribute array"); } presentPseudonym = true; } else // no nym { pseudonymAttribIndex = 0; } bool verifyCommitments = (committed != null && committed.Length > 0); if (verifyCommitments) { Array.Sort(committed); } ProtocolHelper.VerifyTokenSignature(ip, upt); int dArraySize = disclosed.Length + 2; GroupElement[] dBases = new GroupElement[dArraySize]; FieldZqElement[] dExponents = new FieldZqElement[dArraySize]; dBases[0] = ip.G[0]; dExponents[0] = ip.Zq.One; // g0^1 dBases[1] = ip.G[n + 1]; dExponents[1] = ProtocolHelper.ComputeXt(ip, upt.TI, upt.IsDeviceProtected); // gt^xt FieldZqElement[] disclosedX = new FieldZqElement[disclosedAttributes.Length]; int aPreImageArraySize = 2 + (n - disclosed.Length) + (upt.IsDeviceProtected ? 1 : 0); GroupElement[] aPreImageBases = new GroupElement[aPreImageArraySize]; FieldZqElement[] aPreImageExponents = new FieldZqElement[aPreImageArraySize]; // aPreImage arrays' index 0 values depend on the dArray values; they will be filled out later aPreImageBases[1] = upt.H; aPreImageExponents[1] = this.r[0]; // h^r0 int dIndex = 0; int uIndex = 1; int cIndex = 0; int pseudonymResponseIndex = 0; int[] commitmentResponseIndices = verifyCommitments ? new int[committed.Length] : null; for (int i = 1; i <= n; i++) { if (disclosed.Contains(i)) { disclosedX[dIndex] = ProtocolHelper.ComputeXi(ip, i - 1, disclosedAttributes[dIndex]); dBases[dIndex + 2] = ip.G[i]; dExponents[dIndex + 2] = disclosedX[dIndex]; dIndex++; } else { aPreImageBases[uIndex + 1] = ip.G[i]; aPreImageExponents[uIndex + 1] = this.r[uIndex]; // gi^ri if (presentPseudonym) { if (pseudonymAttribIndex == i) { pseudonymResponseIndex = uIndex; } } if (verifyCommitments) { if (committed.Contains(i)) { // remember which response correspond to which commitment commitmentResponseIndices[cIndex] = uIndex; cIndex++; } } uIndex++; } } if (pseudonymAttribIndex == DeviceAttributeIndex) { pseudonymResponseIndex = this.r.Length - 1; // r_d is the last response in the array } byte[] unused; // verifier doesn't use the returned message for device FieldZqElement c = ProtocolHelper.GenerateChallenge(ip, upt, this.a, pseudonymAttribIndex, this.ap, this.ps, message, messageD, disclosed, disclosedX, committed, this.Commitments, out unused); aPreImageBases[0] = Gq.MultiExponentiate(dBases, dExponents); aPreImageExponents[0] = c.Negate(); // g0.gt^xt.Product[gi^xi]_(for disclosed i) if (upt.IsDeviceProtected) { aPreImageBases[aPreImageArraySize - 1] = ip.Gd; aPreImageExponents[aPreImageArraySize - 1] = this.r[this.r.Length - 1]; // gd^rd } HashFunction hash = ip.HashFunction; hash.Hash(Gq.MultiExponentiate(aPreImageBases, aPreImageExponents)); if (!this.a.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } if (presentPseudonym) { hash.Hash(Gq.MultiExponentiate(new GroupElement[] { ps, gs }, new FieldZqElement[] { c, r[pseudonymResponseIndex] })); if (!this.ap.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid pseudonym"); } } if (verifyCommitments) { GroupElement[] cBases = new GroupElement[3]; FieldZqElement[] cExponents = new FieldZqElement[3]; cBases[1] = Gq.G; cBases[2] = ip.G[1]; cExponents[0] = c; for (int i = 0; i < commitmentResponseIndices.Length; i++) { CommitmentValues commitment = this.Commitments[i]; cBases[0] = commitment.TildeC; cExponents[1] = this.r[commitmentResponseIndices[i]]; cExponents[2] = commitment.TildeR; hash.Hash(Gq.MultiExponentiate(cBases, cExponents)); if (!commitment.TildeA.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid commitment " + committed[i]); } } } } catch (ArgumentException) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } catch (IndexOutOfRangeException) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } }
public Issuer(IssuerKeyAndParameters ikap, int numberOfTokens, byte[][] A, byte[] TI, GroupElement hd, FieldZqElement[] preGeneratedW) : this(ikap, numberOfTokens, ProtocolHelper.ComputeIssuanceInput(ikap.IssuerParameters, A, TI, hd), preGeneratedW) { }
internal static FieldZqElement GenerateChallenge(IssuerParameters ip, UProveToken upt, byte[] a, int pseudonymIndex, byte[] ap, GroupElement Ps, byte[] m, byte[] md, int[] disclosed, FieldZqElement[] disclosedX, int[] committed, CommitmentValues[] commitments, out byte[] mdPrime) { bool hasCommitments = (committed != null && committed.Length > 0); if (hasCommitments) { if (committed.Length != commitments.Length) { throw new ArgumentException("Inconsistent committed indices and commitment values"); } } HashFunction hash = ip.HashFunction; hash.Hash(ComputeTokenID(ip, upt)); hash.Hash(a); hash.Hash(disclosed); hash.Hash(disclosedX); if (!hasCommitments) { hash.HashNull(); // C hash.HashNull(); // < {tildeC} > hash.HashNull(); // < {tildeA} > } else { hash.Hash(committed); hash.Hash(commitments.Length); // length of < {tildeC} > for (int i = 0; i < commitments.Length; i++) { hash.Hash(commitments[i].TildeC); } hash.Hash(commitments.Length); // length of < {tildeA} > for (int i = 0; i < commitments.Length; i++) { hash.Hash(commitments[i].TildeA); } } hash.Hash(pseudonymIndex == PresentationProof.DeviceAttributeIndex ? 0 : pseudonymIndex); hash.Hash(ap); hash.Hash(Ps); hash.Hash(m); mdPrime = hash.Digest; if (upt.IsDeviceProtected) { hash = ip.HashFunction; hash.Hash(md); hash.Hash(mdPrime); return(ip.Zq.GetElementFromDigest(hash.Digest)); } else { return(ip.Zq.GetElementFromDigest(mdPrime)); } }
// Private helper function private static byte[] ComputeChallenge(IssuerParameters ip, GroupElement h0, GroupElement CGamma, GroupElement Ch0, GroupElement[] C, GroupElement tildeD, GroupElement tildeCgamma, GroupElement tildeT, GroupElement[] tildeC, byte[] message) { HashFunction H = ip.HashFunction; H.Hash(ip.Digest(false)); H.Hash(h0); H.Hash(CGamma); H.Hash(Ch0); H.Hash(C); H.Hash(tildeD); H.Hash(tildeCgamma); H.Hash(tildeT); H.Hash(tildeC); H.Hash(message); byte[] digest = H.Digest; #if DEBUG Debug.WriteLine("h0 = " + BitConverter.ToString(h0.GetEncoded())); Debug.WriteLine("CGamma = " + BitConverter.ToString(CGamma.GetEncoded())); Debug.WriteLine("Ch0 = " + BitConverter.ToString(Ch0.GetEncoded())); if (tildeC != null) { Debug.WriteLine("tildeC[0] = " + BitConverter.ToString(tildeC[0].GetEncoded())); } Debug.WriteLine("tildeD = " + BitConverter.ToString(tildeD.GetEncoded())); Debug.WriteLine("tildeT = " + BitConverter.ToString(tildeT.GetEncoded())); Debug.WriteLine("tildeCgamma = " + BitConverter.ToString(tildeCgamma.GetEncoded())); Debug.WriteLine("digest = " + BitConverter.ToString(digest)); #endif return(digest); }
internal void OnDeserialized(StreamingContext context) { if (_uidp == null) throw new UProveSerializationException("uidp"); if (_h == null) throw new UProveSerializationException("h"); if (_sigmaZPrime == null) throw new UProveSerializationException("szp"); if (_sigmaCPrime == null) throw new UProveSerializationException("scp"); if (_sigmaRPrime == null) throw new UProveSerializationException("srp"); // default to false if not provided if (_isDeviceProtected == null) _isDeviceProtected = false; this.uidp = _uidp.ToByteArray(); this.h = _h.ToGroupElement(Serializer.ip); this.ti = _ti.ToByteArray(); this.pi = _pi.ToByteArray(); this.sigmaZPrime = _sigmaZPrime.ToGroupElement(Serializer.ip); this.sigmaCPrime = _sigmaCPrime.ToFieldZqElement(Serializer.ip.Zq); this.sigmaRPrime = _sigmaRPrime.ToFieldZqElement(Serializer.ip.Zq); this.isDeviceProtected = _isDeviceProtected.Value; }
GroupElement IDevicePresentationContext.GetInitialWitnessesAndPseudonym(byte[] scope, out GroupElement apPrime, out GroupElement Ps) { // return a_d, ap', and p_s from page 19 u-prove spec. // the scope-exclusive pseudonym derivation function seems to be different from what is used // in U-Prove, so if a smartcard-based pseudonym is requested, better to call it directly without using this interface. //this.device.ProofSession = this.device.device.BeginCommitment(this.device.proverID); if (this.device.credID != -1) { try { // call GetPresCommitment, to ensure correct counter value on hw card. int credStatus = this.device.device.GetCreadentialStatus((byte)this.device.credID); cOut.write("cred status : GetInitialWitnessesAndPseudonym " + credStatus); if (credStatus == 0) { this.device.device.GetIssuanceCommitment((byte)this.device.credID); } else if (credStatus == 2) { this.device.device.GetPresCommitment(this.device.proverID, this.device.credID); } } catch (ErrorCode ex) { cOut.write("Counter do not have the correct value " + ex.Message); DebugUtils.DebugPrintErrorCodes(ex); this.device.device.EndCommitment(); throw; } } byte[] a_dBig = this.device.device.GetDeviceCommitment(true); #if DEBUG this.comForDebug = a_dBig; #endif byte[] apPrimeBig = this.device.device.GetScopeExclusiveCommitment(scope, true); byte[] psBig = this.device.device.GetScopeExclusivePseudonym(scope, true); this.device.device.EndCommitment(); apPrime = this.device.Gq.CreateGroupElement(apPrimeBig); Ps = this.device.Gq.CreateGroupElement(psBig); return this.device.Gq.CreateGroupElement(a_dBig); }
/// <summary> /// Returns <code>this*a</code>. /// </summary> /// <param name="a">The operand.</param> /// <returns>A group element.</returns> public abstract GroupElement Multiply(GroupElement a);
/// <summary> /// Constructs an Issuer parameters instance. /// </summary> /// <param name="uidp">The Issuer parameters UID.</param> /// <param name="group">The group description.</param> /// <param name="uidh">The hash algorithm identifier.</param> /// <param name="g">The generator values.</param> /// <param name="gd">The Device generator, or null.</param> /// <param name="e">The encoding bytes.</param> /// <param name="s">The specification bytes.</param> /// <param name="usesRecommendedParameters">Indicates if the group and g array uses the recommended parameters.</param> public IssuerParameters(byte[] uidp, Group group, string uidh, GroupElement[] g, GroupElement gd, byte[] e, byte[] s, bool usesRecommendedParameters) { this.uidp = uidp; this.group = group; this.uidh = uidh; this.g = g; this.gd = gd; this.e = e; this.s = s; this.usesRecommendedParameters = usesRecommendedParameters; IssuerParameters.serializer = new Serializer(); }
/// <summary> /// Verifies that e is a group element. /// </summary> /// <param name="e">The element to test.</param> /// <exception cref="InvalidUProveArtifactException"> /// Thrown if e is not in the group.</exception> public abstract void ValidateGroupElement(GroupElement e);
/// <summary> /// Hash a GroupElement. /// </summary> /// <param name="value">A GroupElement to be hashed.</param> public void Hash(GroupElement value) { if (value == null) { HashNull(); return; } value.UpdateHash(this); }
/// <summary> /// Convert a base64 string to a GroupElement[] using a specific Group object. /// </summary> /// <param name="encodedElements">The encoded string to convert.</param> /// <param name="group">The group object to use.</param> /// <returns>The converted object.</returns> public static GroupElement[] ToGroupElementArray(this String[] encodedElements, Group group) { if (encodedElements == null) return null; if (group == null) throw new ArgumentNullException("group"); GroupElement[] groupElements = new GroupElement[encodedElements.Length]; for (int i = 0; i < encodedElements.Length; i++) { groupElements[i] = encodedElements[i].ToGroupElement(group); } return groupElements; }
public void Verify(IssuerParameters ip, int[] disclosed, byte[] message, byte[] messageD, UProveToken upt) { GroupElement gs = null; Verify(ip, disclosed, null, 0, gs, message, messageD, upt); }
public Pseudonym(GroupElement A, GroupElement P, BigInteger R) { this.A = A; this.P = P; this.R = R; }
public void Verify(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, byte[] pseudonymScope, byte[] message, byte[] messageD, UProveToken upt) { GroupElement gs = ProtocolHelper.GenerateScopeElement(ip.Gq, pseudonymScope); Verify(ip, disclosed, committed, pseudonymAttribIndex, gs, message, messageD, upt); }
public static IssuerParameters convertIssuerParametersComposite(IssuerParametersComposite ipc, SessionData sessionData) { IssuerParameters ip = new IssuerParameters(); ip.E = ipc.E; if (sessionData.group == null) { GroupDescription sGroup = convertSubgroupDescription(ipc.Gq); ip.Gq = sGroup; } else { ip.Gq = sessionData.group; } GroupElement[] geArray = new GroupElement[ipc.G.Length]; for (int i = 0; i < ipc.G.Length; i++) { geArray[i] = ip.Gq.CreateGroupElement(ipc.G[i]); } ip.G = geArray; if (ipc.UsesRecommendedParameters && ipc.Gd == null) { ip.Gd = sessionData.parameterSet.Gd; } else if (ipc.Gd != null) { ip.Gd = ip.Gq.CreateGroupElement(ipc.Gd); } else { ip.Gd = ip.Gq.CreateGroupElement(ipc.Gq.Gd); //sessionData.groupElement;// parametersSet.Gd; } ip.S = ipc.S; ip.UidH = ipc.UidH; ip.UidP = ipc.UidP; ip.UsesRecommendedParameters = ipc.UsesRecommendedParameters; sessionData.group = ip.Gq; sessionData.groupElement = ip.Gd; return ip; }
private void Precompute(GroupElement gamma, FieldZqElement[] preGenW) { IssuerParameters ip = ikap.IssuerParameters; Group Gq = ip.Gq; FieldZq Zq = ip.Zq; sigmaZ = gamma.Exponentiate(ikap.PrivateKey); if (preGenW == null) { w = Zq.GetRandomElements(numberOfTokens, false); } else { w = preGenW; } sigmaA = new GroupElement[numberOfTokens]; sigmaB = new GroupElement[numberOfTokens]; for (int i = 0; i < numberOfTokens; i++) { sigmaA[i] = Gq.G.Exponentiate(w[i]); sigmaB[i] = gamma.Exponentiate(w[i]); } state = State.Initialized; }
private void InitDevice(ParameterSet set) { if (device == null) { if (UseVirtualDevice) { device = new VirtualDevice(set, new BigInteger(1, deviceSecret)); } else { // use a smartcard device = new SmartCardDevice(set.Group, set.Gd, smartCardParam); } Gq = set.Group; HashFunctionOID = SecurityLevelUtils.getHashfunction(set); hash = new HashFunction(HashFunctionOID); Gd = set.Gd; } }
public Prover(IssuerParameters ip, int numberOfTokens, byte[][] A, byte[] TI, byte[] PI, GroupElement hd) : this(ip, numberOfTokens, A, TI, PI, hd, null) { }
/// <summary> /// Constructs a new <code>PresentationProof</code> instance. /// </summary> /// <param name="disclosedAttributes">The disclosed attributes.</param> /// <param name="a">The <code>a</code> value.</param> /// <param name="ap">The <code>ap</code> value.</param> /// <param name="ps">The <code>Ps</code> value.</param> /// <param name="r">The <code>r</code> values.</param> /// <param name="commitments">The commitments values.</param> public PresentationProof(byte[][] disclosedAttributes, byte[] a, byte[] ap, GroupElement ps, FieldZqElement[] r, CommitmentValues[] commitments) { this.disclosedAttributes = disclosedAttributes; this.a = a; this.ap = ap; this.ps = ps; this.r = r; this.commitments = commitments; }
public Prover(IssuerParameters ip, int numberOfTokens, byte[][] A, byte[] TI, byte[] PI, GroupElement hd, ProverRandomData preGeneratedRandomData) : this(ip, numberOfTokens, ProtocolHelper.ComputeIssuanceInput(ip, A, TI, hd), TI, PI, preGeneratedRandomData, hd != null, DefaultBatchValidationSecurityLevel) { }
public static PresentationProof Generate(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, IDevicePresentationContext deviceContext, UProveKeyAndToken upkt, byte[][] attributes, ProofGenerationRandomData preGenW, out FieldZqElement[] tildeO) { CommitmentPrivateValues cpv; PresentationProof proof = Generate(ip, disclosed, committed, pseudonymAttribIndex, gs, message, messageD, deviceContext, upkt, attributes, preGenW, out cpv); tildeO = cpv.TildeO; return proof; }
public Issuer(IssuerKeyAndParameters ikap, int numberOfTokens, byte[][] A, byte[] TI, GroupElement hd) : this(ikap, numberOfTokens, ProtocolHelper.ComputeIssuanceInput(ikap.IssuerParameters, A, TI, hd), null) { }
/// <summary> /// Computes the value <c>gamma</c>, an input to the issuance protocol. /// </summary> /// <param name="ip">The issuer parameters</param> /// <param name="A"> The attribute values, or null if the token contains no attributes </param> /// <param name="TI">The token information field</param> /// <param name="hd">The device public key, or <c>null</c> if device binding is not supported by the issuer paramters.</param> /// <returns>The group element gamma </returns> public static GroupElement ComputeIssuanceInput(IssuerParameters ip, byte[][] A, byte[] TI, GroupElement hd) { if (ip == null) { throw new ArgumentNullException("Issuer parameters are null"); } int n = 0; bool supportDevice = (hd != null); if (supportDevice && !ip.IsDeviceSupported) { throw new InvalidOperationException("Issuer parameters does not support devices"); } if (A != null) { n = A.Length; } Group Gq = ip.Gq; GroupElement gamma = ip.G[0]; for (int i = 0; i < n; i++) { FieldZqElement xi = ComputeXi(ip, i, A[i]); gamma = gamma * ip.G[i+1].Exponentiate(xi); } FieldZqElement xt = ComputeXt(ip, TI, supportDevice); gamma = gamma * ip.G[n+1].Exponentiate(xt); // Multiply-in the device public key for device-protected tokens if (supportDevice) { gamma = gamma * hd; } return gamma; }
/// <summary> /// Compute a product of powers. /// Return the product of the <code>bases[i].Exponentiate(exponents[i])</code> for <c>i</c> from <c>0</c> to <c>bases.Length -1</c>. /// The inputs <c>bases</c> and <c>exponents</c> must have the same length /// </summary> /// <param name="bases">Group elements array.</param> /// <param name="exponents">Field elements array.</param> /// <returns>Multi-exponentiation of the group elements to the field elements.</returns> public abstract GroupElement MultiExponentiate(GroupElement[] bases, FieldZqElement[] exponents);
/// <summary> /// Generates a presentation proof including optionally presenting a pseudonym, creating attribute commitments, and passing pre-generated random values. /// </summary> /// <param name="ip">The issuer parameters corresponding to <code>upkt</code>.</param> /// <param name="disclosed">An ordered array of disclosed attribute indices.</param> /// <param name="committed">An ordered array of committed attribute indices.</param> /// <param name="pseudonymAttribIndex">Index of the attribute used to create a scope-exclusive pseudonym, or 0 if no pseudonym is to be presented. The index must not be part of the disclosed attributes.</param> /// <param name="gs">The pseudonym scope element, or null if no pseudonym is to be presented.</param> /// <param name="message">The presentation message.</param> /// <param name="messageD">The message for the Device, or null.</param> /// <param name="deviceContext">The active device context, if token is device-protected, or null.</param> /// <param name="upkt">The U-Proke key and token.</param> /// <param name="attributes">The token attributes.</param> /// <param name="preGenW">Optional pregenerated random data for the proof generation.</param> /// <param name="cpv">Returned commitment private values if commitments are computed.</param> /// <returns>A presentation proof.</returns> internal static PresentationProof Generate(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, IDevicePresentationContext deviceContext, UProveKeyAndToken upkt, byte[][] attributes, ProofGenerationRandomData preGenW, out CommitmentPrivateValues cpv) { if (upkt.Token.IsDeviceProtected && deviceContext == null) { throw new ArgumentNullException("Device context is not initialized"); } bool generateCommitments = (committed != null && committed.Length > 0); FieldZqElement[] tildeO = null; // make sure disclosed and committed lists are sorted if (disclosed == null) { // can't be null later, so make it an empty array disclosed = new int[] { }; } Array.Sort(disclosed); if (generateCommitments) { Array.Sort(committed); } int n = 0; if (ip.E != null) { n = ip.E.Length; if (n != attributes.Length) { throw new ArgumentException("number of attributes is inconsistent with issuer parameters"); } } bool presentPseudonym = false; if (gs != null) { if (pseudonymAttribIndex < 1 || (pseudonymAttribIndex > n && pseudonymAttribIndex != DeviceAttributeIndex)) { throw new ArgumentException("pseudonymAttribIndex must be between 1 and " + n + " (inclusive)"); } if (disclosed.Contains(pseudonymAttribIndex)) { throw new ArgumentException("pseudonymAttribIndex cannot be in the disclosed attribute array"); } presentPseudonym = true; } else if (pseudonymAttribIndex > 0) { throw new ArgumentNullException("gs is null"); } else { pseudonymAttribIndex = 0; } Group Gq = ip.Gq; FieldZq Zq = ip.Zq; FieldZqElement xt = ProtocolHelper.ComputeXt(ip, upkt.Token.TI, upkt.Token.IsDeviceProtected); ProofGenerationRandomData random; if (preGenW == null) { random = ProofGenerationRandomData.Generate(n - disclosed.Length, generateCommitments ? committed.Length : 0, Zq, upkt.Token.IsDeviceProtected); } else { random = preGenW; } // set up the multi-exponentiation arrays, with h^w0 as the first term int multiExpArraySize = 1 + (n - disclosed.Length) + (upkt.Token.IsDeviceProtected ? 1 : 0); GroupElement[] bases = new GroupElement[multiExpArraySize]; FieldZqElement[] exponents = new FieldZqElement[multiExpArraySize]; int multiExpIndex = 0; bases[multiExpIndex] = upkt.Token.H; exponents[multiExpIndex++] = random.W0; FieldZqElement[] x = new FieldZqElement[n]; int uIndex = 0; int dIndex = 0; int cIndex = 0; PresentationProof proof = new PresentationProof(); proof.DisclosedAttributes = new byte[disclosed.Length][]; int pseudonymRandomizerIndex = 0; if (generateCommitments) { proof.Commitments = new CommitmentValues[committed.Length]; tildeO = new FieldZqElement[committed.Length]; } HashFunction hash = ip.HashFunction; GroupElement[] cBases = new GroupElement[2] { Gq.G, ip.G[1] }; for (int i = 0; i < n; i++) { x[i] = ProtocolHelper.ComputeXi(ip, i, attributes[i]); if (!disclosed.Contains(i + 1)) { bases[multiExpIndex] = ip.G[i + 1]; exponents[multiExpIndex++] = random.W[uIndex]; if (presentPseudonym) { if (pseudonymAttribIndex == (i + 1)) { pseudonymRandomizerIndex = uIndex; } } if (generateCommitments && committed.Contains(i + 1)) { GroupElement tildeC = ip.Gq.MultiExponentiate(cBases, new FieldZqElement[2] { x[i], random.TildeO[cIndex] }); tildeO[cIndex] = random.TildeO[cIndex]; GroupElement temp2 = ip.Gq.MultiExponentiate(cBases, new FieldZqElement[2] { random.W[uIndex], random.TildeW[cIndex] }); hash.Hash(temp2); byte[] tildeA = hash.Digest; proof.Commitments[cIndex] = new CommitmentValues(tildeC, tildeA, null); cIndex++; } uIndex++; } else if (generateCommitments && committed.Contains(i + 1)) { throw new ArgumentException("attribute " + (i + 1) + " cannot be both disclosed and committed"); } else { proof.DisclosedAttributes[dIndex] = attributes[i]; dIndex++; } } GroupElement aPreImage; if (upkt.Token.IsDeviceProtected) { GroupElement ad; // pseudonym computed by device if (presentPseudonym && pseudonymAttribIndex == DeviceAttributeIndex) { GroupElement apPrime; GroupElement Ps; ad = deviceContext.GetInitialWitnessesAndPseudonym(gs, out apPrime, out Ps); hash.Hash(apPrime * gs.Exponentiate(random.Wd)); proof.Ap = hash.Digest; proof.Ps = Ps; } else { ad = deviceContext.GetInitialWitness(); } bases[multiExpIndex] = ip.Gd; exponents[multiExpIndex++] = random.Wd; aPreImage = Gq.MultiExponentiate(bases, exponents) * ad; } else { aPreImage = Gq.MultiExponentiate(bases, exponents); } hash.Hash(aPreImage); proof.a = hash.Digest; // pseudonym derived from one token attribute if (presentPseudonym && pseudonymAttribIndex != DeviceAttributeIndex) { hash.Hash(gs.Exponentiate(random.W[pseudonymRandomizerIndex])); proof.Ap = hash.Digest; proof.Ps = gs.Exponentiate(x[pseudonymAttribIndex - 1]); } byte[] mdPrime; FieldZqElement c = ProtocolHelper.GenerateChallenge(ip, upkt.Token, proof.a, pseudonymAttribIndex, proof.ap, proof.Ps, message, messageD, disclosed, GetDisclosedX(disclosed, x), committed, proof.Commitments, out mdPrime); proof.r = new FieldZqElement[1 + n - disclosed.Length + (upkt.Token.IsDeviceProtected ? 1 : 0)]; // r_0, {r_i} for undisclosed i, r_d proof.r[0] = c * upkt.PrivateKey + random.W0; uIndex = 1; for (int i = 1; i <= n; i++) { if (!disclosed.Contains(i)) { proof.r[uIndex] = c.Negate() * x[i - 1] + random.W[uIndex - 1]; uIndex++; } } if (upkt.Token.IsDeviceProtected) { proof.r[proof.r.Length - 1] = deviceContext.GetDeviceResponse(messageD, mdPrime, ip.HashFunctionOID) + random.Wd; } if (generateCommitments) { for (int i = 0; i < committed.Length; i++) { proof.Commitments[i].TildeR = c.Negate() * random.TildeO[i] + random.TildeW[i]; } } random.Clear(); cpv = new CommitmentPrivateValues(tildeO); return(proof); }
public static PresentationProof Generate(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, IDevicePresentationContext deviceContext, UProveKeyAndToken upkt, byte[][] attributes, ProofGenerationRandomData preGenW, out FieldZqElement[] tildeO) { CommitmentPrivateValues cpv; PresentationProof proof = Generate(ip, disclosed, committed, pseudonymAttribIndex, gs, message, messageD, deviceContext, upkt, attributes, preGenW, out cpv); tildeO = cpv.TildeO; return(proof); }
/// <summary> /// Generates the second issuance message. /// </summary> /// <param name="message">The first issuance message.</param> /// <returns>The second issuance message.</returns> public SecondIssuanceMessage GenerateSecondMessage(FirstIssuanceMessage message) { if (state != State.Initialized) { throw new InvalidOperationException("Prover not initialized properly"); } Group Gq = ip.Gq; this.sigmaZ = message.sigmaZ; sigmaZPrime = new GroupElement[numberOfTokens]; sigmaAPrime = new GroupElement[numberOfTokens]; sigmaBPrime = new GroupElement[numberOfTokens]; sigmaCPrime = new FieldZqElement[numberOfTokens]; FieldZqElement[] sigmaC = new FieldZqElement[numberOfTokens]; for (int i = 0; i < numberOfTokens; i++) { FieldZqElement blindingExponent = alpha[i]; sigmaZPrime[i] = message.sigmaZ.Exponentiate(blindingExponent); sigmaAPrime[i] = t1[i] * message.sigmaA[i]; sigmaBPrime[i] = sigmaZPrime[i].Exponentiate(beta1[i]) * t2[i] * message.sigmaB[i].Exponentiate(blindingExponent); HashFunction hash = ip.HashFunction; hash.Hash(h[i]); hash.Hash(PI); hash.Hash(sigmaZPrime[i]); hash.Hash(sigmaAPrime[i]); hash.Hash(sigmaBPrime[i]); sigmaCPrime[i] = ip.Zq.GetElementFromDigest(hash.Digest); sigmaC[i] = sigmaCPrime[i] + beta1[i]; } state = State.Second; return new SecondIssuanceMessage(sigmaC); }
public static PresentationProof Generate(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, byte[] pseudonymScope, byte[] message, byte[] messageD, IDevicePresentationContext deviceContext, UProveKeyAndToken upkt, byte[][] attributes, ProofGenerationRandomData preGenW, out FieldZqElement[] tildeO) { GroupElement gs = ProtocolHelper.GenerateScopeElement(ip.Gq, pseudonymScope); return(Generate(ip, disclosed, committed, pseudonymAttribIndex, gs, message, messageD, deviceContext, upkt, attributes, preGenW, out tildeO)); }
internal static FieldZqElement GenerateChallenge(IssuerParameters ip, UProveToken upt, byte[] a, int pseudonymIndex, byte[] ap, GroupElement Ps, byte[] m, byte[] md, int[] disclosed, FieldZqElement[] disclosedX, int[] committed, CommitmentValues[] commitments, out byte[] mdPrime) { bool hasCommitments = (committed != null && committed.Length > 0); if (hasCommitments) { if (committed.Length != commitments.Length) { throw new ArgumentException("Inconsistent committed indices and commitment values"); } } HashFunction hash = ip.HashFunction; hash.Hash(ComputeTokenID(ip, upt)); hash.Hash(a); hash.Hash(disclosed); hash.Hash(disclosedX); if (!hasCommitments) { hash.HashNull(); // C hash.HashNull(); // < {tildeC} > hash.HashNull(); // < {tildeA} > } else { hash.Hash(committed); hash.Hash(commitments.Length); // length of < {tildeC} > for (int i = 0; i < commitments.Length; i++) { hash.Hash(commitments[i].TildeC); } hash.Hash(commitments.Length); // length of < {tildeA} > for (int i = 0; i < commitments.Length; i++) { hash.Hash(commitments[i].TildeA); } } hash.Hash(pseudonymIndex == PresentationProof.DeviceAttributeIndex ? 0 : pseudonymIndex); hash.Hash(ap); hash.Hash(Ps); hash.Hash(m); mdPrime = hash.Digest; if (upt.IsDeviceProtected) { hash = ip.HashFunction; hash.Hash(md); hash.Hash(mdPrime); return ip.Zq.GetElementFromDigest(hash.Digest); } else { return ip.Zq.GetElementFromDigest(mdPrime); } }
/// <summary> /// Hash a GroupElement array. /// </summary> /// <param name="values">An array of GroupElements to be hashed.</param> public void Hash(GroupElement[] values) { if (values == null) { HashNull(); } else { Hash(values.Length); foreach (GroupElement i in values) { i.UpdateHash(this); } } }