//********************************************************* // // Copyright (c) Microsoft. All rights reserved. // This code is licensed under the Apache License Version 2.0. // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. // //********************************************************* package com.microsoft.uprove; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import com.microsoft.uprove.FieldZq.ZqElement; /** * Parameters indicating the manner in which an {@link IssuerKeyAndParameters} * instance is to be generated. * <p> * <code>IssuerKeyAndParameters</code> objects are generated by configuring an * instance of this class and then invoking the instance's * {@link #generate() generate} method. The parameters that affect * <code>IssuerKeyAndParameters</code> generation are: * </p> * * <table border="1" cellpadding="5" summary="Issuer key and parameters generation parameters"> * <tr> * <th>Parameter</th> * <th>Default Value</th> * <th>Description</th> * </tr> * * <tr> * <td>Issuer Parameters UID</td> * <td><code>null</code></td> * <td>The unique identifier of the Issuer parameters. This parameter MUST be set * via the {@link #setParametersUID(byte[]) setParametersUID} method. * The SDK does not interpret Issuer parameters UID values.</td> * </tr> * * <tr> * <td>Prime Order Group</td> * <td><code>null</code></td> * <td>An instance of the mathematical group in which all * cryptographic operations will take place. If none is specified, the * default group generated by * {@link * com.microsoft.uprove.DefaultSubgroupFactory} * will be used.</td> * </tr> * * <tr> * <td>Hash Algorithm</td> * <td><code>null</code></td> * <td>The name of the <code>MessageDigest</code> algorithm to be used for * cryptographic operations. If none is specified, the SHA variant matching * the prime order group size is used.</td> * </tr> * * <tr> * <td>Encoding Bytes</td> * <td><code>null</code></td> * <td>The array of encoding bytes specifying how the corresponding attributes will be * encoded in tokens issued using the generated issuer parameters. The length of this * parameter defines the number of token attributes supported by the issuer parameters. * This parameter MUST be set via the {@link #setEncodingBytes(byte[]) setEncodingBytes} method.</td> * </tr> * * <tr> * <td>Specification</td> * <td><code>null</code></td> * <td>The application-specific specification field. This parameter MUST be set * via the {@link #setSpecification(byte[]) setSpecification} method. * The SDK does not interpret Specification values.</td> * </tr> */ public final class IssuerSetupParameters { // the parameters UID private byte[] parametersUID; // the prime order group private PrimeOrderGroup group; // the hash algorithm UID private String hashAlgorithmUID; // the hash booleans private byte[] encodingBytes; // the specification private byte[] specification; // support Device boolean private boolean supportDevice = false; /** * Sets the Issuer parameters UID. * * @param parametersUID an Issuer parameters UID. */ public void setParametersUID(byte[] parametersUID) { this.parametersUID = parametersUID; } /** * Returns the Issuer parameters UID. * @return an Issuer parameters UID. */ public byte[] getParametersUID() { return parametersUID; } /** * Sets the Issuer parameters prime order group. * @param group a prime order group. */ public void setGroup(PrimeOrderGroup group) { this.group = group; } /** * Returns the Issuer parameters prime order group. * @return a prime order group. */ public PrimeOrderGroup getGroup() { return group; } /** * Sets the Issuer parameters hash algorithm UID. * @param hashAlgorithmUID a hash algorithm UID. */ public void setHashAlgorithmUID(String hashAlgorithmUID) { this.hashAlgorithmUID = hashAlgorithmUID; } /** * Gets the Issuer parameters hash algorithm UID. * @return a hash algorithm UID. */ public String getHashAlgorithmUID() { return hashAlgorithmUID; } /** * Sets the Issuer parameters encoding bytes. * @param encodingBytes an encoding bytes array. */ public void setEncodingBytes(byte[] encodingBytes) { this.encodingBytes = encodingBytes; } /** * Gets the Issuer parameters encoding bytes. * @return an encoding bytes array. */ public byte[] getEncodingBytes() { return encodingBytes; } /** * Sets the Issuer parameters specification. * @param specification a specification. */ public void setSpecification(byte[] specification) { this.specification = specification; } /** * Gets the Issuer parameters specification. * @return a specification. */ public byte[] getSpecification() { return specification; } /** * Sets the support Device boolean. * @param supportDevice true to support Device, false otherwise. */ public void setSupportDevice(boolean supportDevice) { this.supportDevice = supportDevice; } /** * Gets the support Device boolean. * @return the support Device boolean. */ public boolean getSupportDevice() { return supportDevice; } private int getDefaultGroupSize() { if (hashAlgorithmUID == "SHA-1") { // FIXME: remove support for SHA-1? return 160; } else if (hashAlgorithmUID == "SHA-256") { return 256; } else if (hashAlgorithmUID == "SHA-512") { return 512; } // our default return 256; } /** * Validates <code>this</code> parameters instance. Specifically, the * following tests are made: * <ul> * <li>Does {@link #getParametersUID() getParametersUID} return a * non-<code>null</code> identifier?</li> * <li>If {@link #getGroup() getGroup} returns * non-<code>null</code>, is the group valid?</li> * <li>If {@link #getHashAlgorithmUID() getHashAlgorithmUID} returns * non-<code>null</code>, can the hash algorithm be created?</li> * <li>Does {@link #getEncodingBytes() getEncodingBytes} return a * non-<code>null</code> array?</li> * <li>Does {@link #getSpecification() getSpecification} return a * non-<code>null</code> value?</li> * </ul> * @throws IllegalStateException if <code>this</code> is not in a * suitable state for generating an Issuer. * @throws NoSuchProviderException if the configured * {@link java.security.MessageDigest} provider is not installed. * @throws NoSuchAlgorithmException if the desired * <code>MessageDigest</code> algorithm cannot be found. * @see com.microsoft.uprove.Config#getMessageDigestProvider() */ public void validate() throws NoSuchProviderException, NoSuchAlgorithmException { if (this.parametersUID == null) { throw new IllegalStateException("Issuer parameters UID is not set."); } if (this.hashAlgorithmUID != null) { // can we get a message digest for the specified algorithm? ConfigImpl.getMessageDigest(this.hashAlgorithmUID); } if (this.group != null) { this.group.validate(); } if (this.encodingBytes == null) { throw new IllegalStateException("Encoding bytes parameter is not set."); } } /** * Creates an Issuer key and Parameters object according to * specified generation parameters. * @return an Issuer's private key and parameters, generated as * specified by <code>this</code> parameter instance. * Ownership of the referent is given to the caller. * @throws IllegalStateException if <code>params</code> is not in a * suitable state for generating an Issuer, as indicated by the * {@link #validate() validate} method. * @throws NoSuchProviderException if the configured * {@link java.security.MessageDigest} provider is not installed. * @throws NoSuchAlgorithmException if the desired * <code>MessageDigest</code> algorithm cannot be found. * @see com.microsoft.uprove.Config#getMessageDigestProvider() * @see #validate() */ public IssuerKeyAndParameters generate() throws NoSuchProviderException, NoSuchAlgorithmException { // make sure the parameters are valid validate(); if (this.group == null) { this.group = DefaultSubgroupFactory.getDefaultSubroup(getDefaultGroupSize()); } int size = this.encodingBytes.length + 2 + (supportDevice ? 1 : 0); GroupElement g = this.group.getGenerator(); ZqElement[] privateKey = group.getZq().getRandomElements(size, false); GroupElement[] publicKey = new GroupElement[size]; GroupElement[] proverIssuanceValues = new GroupElement[size]; ZqElement y0 = privateKey[0]; for (int i=0; i<size; i++) { publicKey[i] = g.exponentiate(privateKey[i]); proverIssuanceValues[i] = publicKey[i].exponentiate(y0); } IssuerParameters ip = new IssuerParameters(); ip.setEncodingBytes(this.encodingBytes); ip.setGroup(this.group); ip.setHashAlgorithmUID(this.hashAlgorithmUID); ip.setParametersUID(this.parametersUID); ip.setProverIssuanceValues(ProtocolHelper.getEncodedArray(proverIssuanceValues)); ip.setPublicKey(ProtocolHelper.getEncodedArray(publicKey)); ip.setSpecification(this.specification); return new IssuerKeyAndParameters(ip, privateKey[0].toByteArray()); } }