Deterministic DSA (Java errors)

Hello. I’m having trouble launching this code. It seems to provide two errors and I’m not sure my platform is set up correctly to load the script (appears fine, not sure).

Is there anyone available that could help me troubleshoot the following script and get it operational without upsetting its integrity?

My errors are,

javac deterministicdsa.java
deterministicdsa.java:1: error: class, interface, or enum expected
   We include here a sample implementation of deterministic DSA.  It is
   ^
deterministicdsa.java:2: error: class, interface, or enum expected
   meant for illustration purposes; for instance, this code makes no
                                    ^
2 errors

Also, errors list in MVSC terminal are,

Copyright (C) Microsoft Corporation. All rights reserved.

Try the new cross-platform PowerShell https://aka.ms/pscore6

PS C:\Users\M>  & 'c:\Users\M\.vscode\extensions\vscjava.vscode-java-debug-0.26.0\scripts\launcher.bat' 'C:\Pror=n,suspend=y,address=localhost:61787' '--enable-preview' '-Dfile.encoding=UTF-8' '-cp' 'C:\Users\M\AppData\Loc
Error: Main method not found in class DeterministicDSA, please define the main method as:
or a JavaFX application class must extend javafx.application.Application
PS C:\Users\M>
             >  & 'c:\Users\M\.vscode\extensions\vscjava.vscode-java-debug-0.26.0\scripts\launcher.bat' 'C:\ProError: Main method not found in class DeterministicDSA, please define the main method as:\launcher.bat' 'C:\Pro
   public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
PS C:\Users\M>  & 'c:\Users\M\.vscode\extensions\vscjava.vscode-java-debug-0.26.0\scripts\launcher.bat' 'C:\ProError: Main method not found in class DeterministicDSA, please define the main method as:
   public static void main(String[] args)
or a JavaFX a>  & 'c:\Users\M\.vscode\extensions\vscjava.vscode-java-debug-0.26.0\scripts\launcher.bat' 'C:\Pro   public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
PS C:\Users\M>  & 'c:\Users\M\.vscode\extensions\vscjava.vscode-java-debug-0.26.0\scripts\launcher.bat' 'C:\Program Files\Java\jdk-14.0.1\bin\java.exe' '-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=localhost:62121' '--enable-preview' '-Dfile.encoding=UTF-8' '-cp' 'C:\Users\M\AppData\Local\Temp\vscodesws_e9ae4\jdt_ws\jdt.ls-java-project\bin' 'DeterministicDSA'
Error: Main method not found in class DeterministicDSA, please define the main method as:
   public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
PS C:\Users\M>

And my two output errors in MVSC are,

Syntax error on tokens, delete these tokens

**and** 

DeterministicDSA.java is a non-project file, only syntax errors are reported

And my launcher.bat shows,

@echo off

REM Change code page to UTF-8 for better compatibility.
@chcp.com 65001 > NUL 

REM Execute real command passed by args
%*

Also, I get this in Apache NetBeans (separate projects, neither will launch),

Error: LinkageError occurred while loading main class deterministicdsa.DeterministicDSA
	java.lang.ClassFormatError: Invalid superclass index 0 in class file deterministicdsa/DeterministicDSA
C:\Users\M\AppData\Local\NetBeans\Cache\12.0\executor-snippets\run.xml:111: The following error occurred while executing this line:
C:\Users\M\AppData\Local\NetBeans\Cache\12.0\executor-snippets\run.xml:68: Java returned: 1
BUILD FAILED (total time: 1 second)

**or**

run:
BUILD SUCCESSFUL (total time: 1 second)

And the code is as follows,

   We include here a sample implementation of deterministic DSA.  It is
   meant for illustration purposes; for instance, this code makes no
   attempt at avoiding side-channel leakage of the private key.  It is
   written in the Java programming language.  The actual generation of
   the "random" value k is done in the computek() method.  The Java
   virtual machine (JVM) is assumed to provide the implementation of the
   hash function and of HMAC.

  // ==================================================================

  import java.math.BigInteger;
  import java.security.InvalidKeyException;
  import java.security.MessageDigest;
  import java.security.NoSuchAlgorithmException;
  import javax.crypto.Mac;
  import javax.crypto.spec.SecretKeySpec;

  /**
   * Deterministic DSA signature generation.  This is a sample
   * implementation designed to illustrate how deterministic DSA
   * chooses the pseudorandom value k when signing a given message.
   * This implementation was NOT optimized or hardened against
   * side-channel leaks.
   *
   * An instance is created with a hash function name, which must be
   * supported by the underlying Java virtual machine ("SHA-1" and
   * "SHA-256" should work everywhere).  The data to sign is input
   * through the {@code update()} methods.  The private key is set with
   * {@link #setPrivateKey}.  The signature is obtained by calling
   * {@link #sign}; alternatively, {@link #signHash} can be used to
   * sign some data that has been externally hashed.  The private key
   * MUST be set before generating the signature itself, but message
   * data can be input before setting the key.
   *
   * Instances are NOT thread-safe.  However, once a signature has
   * been generated, the same instance can be used again for another
   * signature; {@link #setPrivateKey} need not be called again if the
   * private key has not changed.  {@link #reset} can also be called to
   * cancel previously input data.  Generating a signature with {@link
   * #sign} (not {@link #signHash}) also implicitly causes a
   * reset.
   *
   * ------------------------------------------------------------------
   * Copyright (c) 2013 IETF Trust and the persons identified as
   * authors of the code.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, is permitted pursuant to, and subject to the license
   * terms contained in, the Simplified BSD License set forth in Section
   * 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
   * (http://trustee.ietf.org/license-info).
   *
   * Technical remarks and questions can be addressed to:
   * pornin@bolet.org
   * ------------------------------------------------------------------
   */

  public class DeterministicDSA {

          private String macName;
          private MessageDigest dig;
          private Mac hmac;
          private BigInteger p, q, g, x;
          private int qlen, rlen, rolen;
		private final int holen;
          private byte[] bx;

          /**
           * Create an instance, using the specified hash function.
           * The name is used to obtain from the JVM an implementation
           * of the hash function and an implementation of HMAC.
           *
           * @param hashName   the hash function name
           * @throws IllegalArgumentException  on unsupported name
           */
          public DeterministicDSA(final String hashName)
          {
                  try {
                          dig = MessageDigest.getInstance(hashName);
                  } catch (final NoSuchAlgorithmException nsae) {
                          throw new IllegalArgumentException(nsae);
                  }
                  if (hashName.indexOf('-') < 0) {
                          macName = "Hmac" + hashName;
                  } else {
                          final StringBuilder sb = new StringBuilder();
                          sb.append("Hmac");
                          final int n = hashName.length();
                          for (int i = 0; i < n; i ++) {
                                  final char c = hashName.charAt(i);
                                  if (c != '-') {
                                          sb.append(c);
                                  }
                          }
                          macName = sb.toString();
                 }
                  try {
                          hmac = Mac.getInstance(macName);
                  } catch (final NoSuchAlgorithmException nsae) {
                          throw new IllegalArgumentException(nsae);
                  }
                  holen = hmac.getMacLength();
          }

          /**
           * Set the private key.
           *
           * @param p   key parameter: field modulus
           * @param q   key parameter: subgroup order
           * @param g   key parameter: generator
           * @param x   private key
           */
          public void setPrivateKey(final BigInteger p, final BigInteger q,
                  final BigInteger g, final BigInteger x)
          {
                  /*
                   * Perform some basic sanity checks.  We do not
                   * check primality of p or q because that would
                   * be too expensive.
                   *
                   * We reject keys where q is longer than 999 bits,
                   * because it would complicate signature encoding.
                   * Normal DSA keys do not have a q longer than 256
                   * bits anyway.
                   */
                  if (p == null || q == null || g == null || x == null
                          || p.signum() <= 0 || q.signum() <= 0
                          || g.signum() <= 0 || x.signum() <= 0
                          || x.compareTo(q) >= 0 || q.compareTo(p) >= 0
                          || q.bitLength() > 999
                          || g.compareTo(p) >= 0 || g.bitLength() == 1
                          || g.modPow(q, p).bitLength() != 1) {
                          throw new IllegalArgumentException(
                                  "invalid DSA private key");
                  }
                  this.p = p;
                  this.q = q;
                  this.g = g;
                  this.x = x;
                  qlen = q.bitLength();
                  if (q.signum() <= 0 || qlen < 8) {
                          throw new IllegalArgumentException(
                                  "bad group order: " + q);
                  }
                  rolen = (qlen + 7) >>> 3;
                  rlen = rolen * 8;

                  /*
                   * Convert the private exponent (x) into a sequence
                   * of octets.
                   */
                  bx = int2octets(x);
          }

          private BigInteger bits2int(final byte[] in)
          {
                  BigInteger v = new BigInteger(1, in);
                  final int vlen = in.length * 8;
                  if (vlen > qlen) {
                          v = v.shiftRight(vlen - qlen);
                  }
                  return v;
          }

          private byte[] int2octets(final BigInteger v)
          {
                  final byte[] out = v.toByteArray();
                  if (out.length < rolen) {
                          final byte[] out2 = new byte[rolen];
                          System.arraycopy(out, 0,
                                  out2, rolen - out.length,
                                  out.length);
                          return out2;
                  } else if (out.length > rolen) {
                          final byte[] out2 = new byte[rolen];
                          System.arraycopy(out, out.length - rolen,
                                  out2, 0, rolen);
                          return out2;
                  } else {
                          return out;
                  }
          }

          private byte[] bits2octets(final byte[] in)
          {
                  final BigInteger z1 = bits2int(in);
                  final BigInteger z2 = z1.subtract(q);
                  return int2octets(z2.signum() < 0 ? z1 : z2);
          }

          /**
           * Set (or reset) the secret key used for HMAC.
           *
           * @param K   the new secret key
           */
          private void setHmacKey(final byte[] K)
          {
                  try {
                          hmac.init(new SecretKeySpec(K, macName));
                  } catch (final InvalidKeyException ike) {
                          throw new IllegalArgumentException(ike);
                  }
          }

          /**
           * Compute the pseudorandom k for signature generation,
           * using the process specified for deterministic DSA.
           *
           * @param h1   the hashed message
           * @return  the pseudorandom k to use
           */
          private BigInteger computek(final byte[] h1)
          {
                  /*
                   * Convert hash value into an appropriately truncated
                   * and/or expanded sequence of octets.  The private
                   * key was already processed (into field bx[]).
                   */
                  final byte[] bh = bits2octets(h1);

                  /*
                   * HMAC is always used with K as key.
                   * Whenever K is updated, we reset the
                   * current HMAC key.
                   */

                  /* step b. */
                  byte[] V = new byte[holen];
                  for (int i = 0; i < holen; i ++) {
                          V[i] = 0x01;
                  }

                  /* step c. */
                  byte[] K = new byte[holen];
                  setHmacKey(K);

                  /* step d. */
                  hmac.update(V);
                  hmac.update((byte)0x00);
                  hmac.update(bx);
                  hmac.update(bh);
                  K = hmac.doFinal();
                  setHmacKey(K);

                  /* step e. */
                  hmac.update(V);
                  V = hmac.doFinal();

                  /* step f. */
                  hmac.update(V);
                  hmac.update((byte)0x01);
                  hmac.update(bx);
                  hmac.update(bh);
                  K = hmac.doFinal();
                  setHmacKey(K);

                  /* step g. */
                  hmac.update(V);
                  V = hmac.doFinal();

                  /* step h. */
                  final byte[] T = new byte[rolen];
                  for (;;) {
                          /*
                           * We want qlen bits, but we support only
                           * hash functions with an output length
                           * multiple of 8;acd hence, we will gather
                           * rlen bits, i.e., rolen octets.
                           */
                          int toff = 0;
                          while (toff < rolen) {
                                  hmac.update(V);
                                  V = hmac.doFinal();
                                  final int cc = Math.min(V.length,
                                          T.length - toff);
                                  System.arraycopy(V, 0, T, toff, cc);
                                  toff += cc;
                          }
                          final BigInteger k = bits2int(T);
                          if (k.signum() > 0 && k.compareTo(q) < 0) {
                                  return k;
                          }

                          /*
                           * k is not in the proper range; update
                           * K and V, and loop.
                           */
                          hmac.update(V);
                          hmac.update((byte)0x00);
                          K = hmac.doFinal();
                          setHmacKey(K);
                          hmac.update(V);
                          V = hmac.doFinal();
                  }
          }

          /**
           * Process one more byte of input data (message to sign).
           *
           * @param in   the extra input byte
           */
          public void update(final byte in)
          {
                  dig.update(in);
          }

          /**
           * Process some extra bytes of input data (message to sign).
           *
           * @param in   the extra input bytes
           */
          public void update(final byte[] in)
          {
                  dig.update(in, 0, in.length);
          }

          /**
           * Process some extra bytes of input data (message to sign).
           *
           * @param in    the extra input buffer
           * @param off   the extra input offset
           * @param len   the extra input length (in bytes)
           */
          public void update(final byte[] in, final int off, final int len)
          {
                  dig.update(in, off, len);
          }

          /**
           * Produce the signature.  {@link #setPrivateKey} MUST have
           * been called.  The signature is computed over the data
           * that was input through the {@code update*()} methods.
           * This engine is then reset (made ready for a new
           * signature generation).
           *
           * @return  the signature
           */
          public byte[] sign()
          {
                  return signHash(dig.digest());
          }

          /**
           * Produce the signature.  {@link #setPrivateKey} MUST
           * have been called.  The signature is computed over the
           * provided hash value (data is assumed to have been hashed
           * externally).  The data that was input through the
           * {@code update*()} methods is ignored, but kept.
           *
           * If the hash output is longer than the subgroup order
           * (the length of q, in bits, denoted 'qlen'), then the
           * provided value {@code h1} can be truncated, provided that
           * at least qlen leading bits are preserved.  In other words,
           * bit values in {@code h1} beyond the first qlen bits are
           * ignored.
           *
           * @param h1   the hash value
           * @return  the signature
           */
          public byte[] signHash(final byte[] h1)
          {
                  if (p == null) {
                          throw new IllegalStateException(
                                  "no private key set");
                  }
                  try {
                          final BigInteger k = computek(h1);
                          final BigInteger r = g.modPow(k, p).mod(q);
                          final BigInteger s = k.modInverse(q).multiply(
                                  bits2int(h1).add(x.multiply(r)))
                                  .mod(q);

                          /*
                           * Signature encoding: ASN.1 SEQUENCE of
                           * two INTEGERs.  The conditions on q
                           * imply that the encoded version of r and
                           * s is no longer than 127 bytes for each,
                           * including DER tag and length.
                           */
                          final byte[] br = r.toByteArray();
                          final byte[] bs = s.toByteArray();
                          final int ulen = br.length + bs.length + 4;
                          final int slen = ulen + (ulen >= 128 ? 3 : 2);
                          final byte[] sig = new byte[slen];
                          int i = 0;
                          sig[i ++] = 0x30;
                          if (ulen >= 128) {
                                  sig[i ++] = (byte)0x81;
                                  sig[i ++] = (byte)ulen;
                          } else {
                                  sig[i ++] = (byte)ulen;
                          }
                          sig[i ++] = 0x02;
                          sig[i ++] = (byte)br.length;
                          System.arraycopy(br, 0, sig, i, br.length);
                          i += br.length;
                          sig[i ++] = 0x02;
                          sig[i ++] = (byte)bs.length;
                          System.arraycopy(bs, 0, sig, i, bs.length);
                          return sig;

                  } catch (final ArithmeticException ae) {
                          throw new IllegalArgumentException(
                                  "DSA error (bad key ?)", ae);
                  }
          }

          /**
           * Reset this engine.  Data input through the {@code
           * update*()} methods is discarded.  The current private key,
           * if one was set, is kept unchanged.
           */
          public void reset()
          {
                  dig.reset();
          }
  }

  // ==================================================================

1 Like

it looks like your first 7 lines are supposed to be commented out.

@JeremyLT I ran it that way (removing top seven lines, and also included “/**’”. It made it worse. It’s something simple and I’m not seeing it (The code is seven years old).

The first 7 lines must be commented out. Java gives up after the first line and is not telling you anything else. Commenting out the first 7 lines will give you errors that you can work with. It might be that you need to use an older version of Java.

@JeremyLT Okay. THAT makes sense. The rest of the errors wasn’t much (suggestions).

Depending on how I comment it out, depends on how many following errors I get (Haven’t tried to run it yet).

If I "/" in the front and nothing at line 7 I still get the following both ways (/ code /*).

“Listening on javadebug
User program running
User program finished”

Second way identified more suggestions for fields not used to be removed.

I’ll try to run it, now. Thanks.

@JeremyLT I ran it “javac deterministicdsa.java” and reported no errors. However, the only thing I received was a “pause” for a brief second and a new return line (command line).

Something isn’t right for the launch. Maybe it’s not compiled properly?

Did the file come with instructions on how to run and use the code?

@JeremyLT No (Actually, Yes, sir. The instructions are commented out and the keys in the white paper, updated Java to make it work and main lines are not). It came from a white paper. It is operational. A few years again, it was expanded with C++ (Information here: https://github.com/weidai11/cryptopp/issues/121 , The code originally came from here, at the end of the paper, https://tools.ietf.org/html/rfc6979, and a C++ library includes their build and versions here, https://www.cryptopp.com/ ).

Nevertheless, because the C++ project reduced its potential, I want to run the java script and build upon it.

With the question asked, I also believe I may know whats wrong with the script, in-part.

I feel, I need to enter the values to calculate and its that’s why it paused and returned nothing (assuming). Also, I expected to be prompted to enter the values (that’s how I would have done it and want it to work in side a console like an app).

If you have any suggestions, I’m all ears.

Thanks.

I don’t mean to be harsh here, but to use the Java code, you’re going to have to know at least the very basics of Java itself. The semantics of the code and the fiddly java toolchain might not be something you’d know right off, but that unclosed comment at the top should have been something you could recognize and fix right away.

I recommend starting with this course to get familiar with Java:

1 Like