content: package im.actor.crypto.primitives.curve25519;
  
  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;
  }
  
  
  }
  