All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.pqc.crypto.gmss.util.WinternitzOTSignature Maven / Gradle / Ivy

Go to download

The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains JCE provider and lightweight API for the Bouncy Castle Cryptography APIs for JDK 1.4.

There is a newer version: 1.79
Show newest version
package org.bouncycastle.pqc.crypto.gmss.util;

import org.bouncycastle.crypto.Digest;

/**
 * This class implements key pair generation and signature generation of the
 * Winternitz one-time signature scheme (OTSS), described in C.Dods, N.P. Smart,
 * and M. Stam, "Hash Based Digital Signature Schemes", LNCS 3796, pages
 * 96–115, 2005. The class is used by the GMSS classes.
 */

public class WinternitzOTSignature
{

    /**
     * The hash function used by the OTS
     */
    private Digest messDigestOTS;

    /**
     * The length of the message digest and private key
     */
    private int mdsize, keysize;

    /**
     * An array of strings, containing the name of the used hash function, the
     * name of the PRGN and the names of the corresponding providers
     */
    // private String[] name = new String[2];
    /**
     * The private key
     */
    private byte[][] privateKeyOTS;

    /**
     * The Winternitz parameter
     */
    private int w;

    /**
     * The source of randomness for OTS private key generation
     */
    private GMSSRandom gmssRandom;

    /**
     * Sizes of the message and the checksum, both
     */
    private int messagesize, checksumsize;

    /**
     * The constructor generates an OTS key pair, using seed0 and
     * the PRNG
     * 

* * @param seed0 the seed for the PRGN * @param digest an array of strings, containing the name of the used hash * function, the name of the PRGN and the names of the * corresponding providers * @param w the Winternitz parameter */ public WinternitzOTSignature(byte[] seed0, Digest digest, int w) { // this.name = name; this.w = w; messDigestOTS = digest; gmssRandom = new GMSSRandom(messDigestOTS); // calulate keysize for private and public key and also the help // array mdsize = messDigestOTS.getDigestSize(); int mdsizeBit = mdsize << 3; messagesize = (int)Math.ceil((double)(mdsizeBit) / (double)w); checksumsize = getLog((messagesize << w) + 1); keysize = messagesize + (int)Math.ceil((double)checksumsize / (double)w); /* * mdsize = messDigestOTS.getDigestLength(); messagesize = * ((mdsize<<3)+(w-1))/w; * * checksumsize = getlog((messagesize< 0) { messDigestOTS.update(hlp, 0, hlp.length); hlp = new byte[messDigestOTS.getDigestSize()]; messDigestOTS.doFinal(hlp, 0); test--; } System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize); hash[i] = (byte)(hash[i] >>> w); counter++; } } c = (messagesize << w) - c; for (int i = 0; i < checksumsize; i += w) { test = c & k; System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize); while (test > 0) { messDigestOTS.update(hlp, 0, hlp.length); hlp = new byte[messDigestOTS.getDigestSize()]; messDigestOTS.doFinal(hlp, 0); test--; } System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize); c >>>= w; counter++; } } else if (w < 8) { int d = mdsize / w; int k = (1 << w) - 1; byte[] hlp = new byte[mdsize]; long big8; int ii = 0; // create signature // first d*w bytes of hash for (int i = 0; i < d; i++) { big8 = 0; for (int j = 0; j < w; j++) { big8 ^= (hash[ii] & 0xff) << (j << 3); ii++; } for (int j = 0; j < 8; j++) { test = (int)(big8 & k); c += test; System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize); while (test > 0) { messDigestOTS.update(hlp, 0, hlp.length); hlp = new byte[messDigestOTS.getDigestSize()]; messDigestOTS.doFinal(hlp, 0); test--; } System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize); big8 >>>= w; counter++; } } // rest of hash d = mdsize % w; big8 = 0; for (int j = 0; j < d; j++) { big8 ^= (hash[ii] & 0xff) << (j << 3); ii++; } d <<= 3; for (int j = 0; j < d; j += w) { test = (int)(big8 & k); c += test; System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize); while (test > 0) { messDigestOTS.update(hlp, 0, hlp.length); hlp = new byte[messDigestOTS.getDigestSize()]; messDigestOTS.doFinal(hlp, 0); test--; } System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize); big8 >>>= w; counter++; } // check bytes c = (messagesize << w) - c; for (int i = 0; i < checksumsize; i += w) { test = c & k; System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize); while (test > 0) { messDigestOTS.update(hlp, 0, hlp.length); hlp = new byte[messDigestOTS.getDigestSize()]; messDigestOTS.doFinal(hlp, 0); test--; } System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize); c >>>= w; counter++; } }// end if(w<8) else if (w < 57) { int d = (mdsize << 3) - w; int k = (1 << w) - 1; byte[] hlp = new byte[mdsize]; long big8, test8; int r = 0; int s, f, rest, ii; // create signature // first a*w bits of hash where a*w <= 8*mdsize < (a+1)*w while (r <= d) { s = r >>> 3; rest = r % 8; r += w; f = (r + 7) >>> 3; big8 = 0; ii = 0; for (int j = s; j < f; j++) { big8 ^= (hash[j] & 0xff) << (ii << 3); ii++; } big8 >>>= rest; test8 = (big8 & k); c += test8; System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize); while (test8 > 0) { messDigestOTS.update(hlp, 0, hlp.length); hlp = new byte[messDigestOTS.getDigestSize()]; messDigestOTS.doFinal(hlp, 0); test8--; } System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize); counter++; } // rest of hash s = r >>> 3; if (s < mdsize) { rest = r % 8; big8 = 0; ii = 0; for (int j = s; j < mdsize; j++) { big8 ^= (hash[j] & 0xff) << (ii << 3); ii++; } big8 >>>= rest; test8 = (big8 & k); c += test8; System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize); while (test8 > 0) { messDigestOTS.update(hlp, 0, hlp.length); hlp = new byte[messDigestOTS.getDigestSize()]; messDigestOTS.doFinal(hlp, 0); test8--; } System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize); counter++; } // check bytes c = (messagesize << w) - c; for (int i = 0; i < checksumsize; i += w) { test8 = (c & k); System.arraycopy(privateKeyOTS[counter], 0, hlp, 0, mdsize); while (test8 > 0) { messDigestOTS.update(hlp, 0, hlp.length); hlp = new byte[messDigestOTS.getDigestSize()]; messDigestOTS.doFinal(hlp, 0); test8--; } System.arraycopy(hlp, 0, sign, counter * mdsize, mdsize); c >>>= w; counter++; } }// end if(w<57) return sign; } /** * This method returns the least integer that is greater or equal to the * logarithm to the base 2 of an integer intValue. * * @param intValue an integer * @return The least integer greater or equal to the logarithm to the base 2 * of intValue */ public int getLog(int intValue) { int log = 1; int i = 2; while (i < intValue) { i <<= 1; log++; } return log; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy