public static byte[] sign(
      final byte[] message, final byte[] publicKey, final byte[] hashedPrivateKey)
      throws GeneralSecurityException {
    // Copying the message to make it thread-safe. Otherwise, if the caller modifies the message
    // between the first and the second hash then it might leak the private key.
    byte[] messageCopy = Arrays.copyOfRange(message, 0, message.length);
    MessageDigest digest = EngineFactory.MESSAGE_DIGEST.getInstance("SHA-512");
    digest.update(hashedPrivateKey, Field25519.FIELD_LEN, Field25519.FIELD_LEN);
    digest.update(messageCopy);
    byte[] r = digest.digest();
    reduce(r);

    byte[] rB = Arrays.copyOfRange(scalarMultWithBase(r).toBytes(), 0, Field25519.FIELD_LEN);
    digest.reset();
    digest.update(rB);
    digest.update(publicKey);
    digest.update(messageCopy);
    byte[] hram = digest.digest();
    reduce(hram);
    byte[] s = new byte[Field25519.FIELD_LEN];
    mulAdd(s, hram, hashedPrivateKey, r);
    return Bytes.concat(rB, s);
  }
Returns the EdDSA signature for the {@code message} based on the {@code hashedPrivateKey}.

@param message to sign
@param publicKey {@link Ed25519#scalarMultWithBaseToBytes(byte[])} of {@code hashedPrivateKey}
@param hashedPrivateKey {@link Ed25519#getHashedScalar(byte[])} of the private key
@return signature for the {@code message}.
@throws GeneralSecurityException if there is no SHA-512 algorithm defined in {@link
    EngineFactory}.MESSAGE_DIGEST.
java_src/src/main/java/com/google/crypto/tink/internal/Ed25519.java