package org.whispersystems.curve25519.java;

public class open {

//CONVERT #include <string.h>
//CONVERT #include "crypto_sign.h"
//CONVERT #include "crypto_hash_sha512.h"
//CONVERT #include "crypto_verify_32.h"
//CONVERT #include "ge.h"
//CONVERT #include "sc.h"

public static int crypto_sign_open(
  Sha512 sha512provider,
  byte[] m, long mlen,
  byte[] sm, long smlen,
  byte[] pk
)
{
  byte[] pkcopy = new byte[32];
  byte[] rcopy = new byte[32];
  byte[] scopy = new byte[32];
  byte[] h = new byte[64];
  byte[] rcheck = new byte[32];
  ge_p3 A = new ge_p3();
  ge_p2 R = new ge_p2();

  if (smlen < 64) return -1;
  if ((sm[63] & 224) != 0) return -1;
  if (ge_frombytes.ge_frombytes_negate_vartime(A,pk) != 0) return -1;

  byte[] pubkeyhash = new byte[64];
  sha512provider.calculateDigest(pubkeyhash,pk,32);

  System.arraycopy(pk, 0, pkcopy, 0, 32);
  System.arraycopy(sm, 0, rcopy, 0, 32);
  System.arraycopy(sm, 32, scopy, 0, 32);

  System.arraycopy(sm, 0, m, 0, (int)smlen);
  System.arraycopy(pkcopy, 0, m, 32, 32);
  sha512provider.calculateDigest(h,m,smlen);
  sc_reduce.sc_reduce(h);

  ge_double_scalarmult.ge_double_scalarmult_vartime(R,h,A,scopy);
  ge_tobytes.ge_tobytes(rcheck,R);
  if (crypto_verify_32.crypto_verify_32(rcheck,rcopy) == 0) {
    System.arraycopy(m, 64, m, 0, (int)(smlen - 64));
    //memset(m + smlen - 64,0,64);
    return 0;
  }

//badsig:
  //memset(m,0,smlen);
  return -1;
}


}
