import java.util.Base64;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.PrivateKey;
import java.security.spec.X509EncodedKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.Signature;

/*
 * Utility Class for Sign/Verify with RSA
 *
 * How to load Java into schema APEXDEV
 * loadjava -force -verbose -resolve -u apexdev/****@localhost/xepdb1 SignatureUtl.java
 *
 * Wrapper Function:
--
create or replace function signatureutl_verify
(
    text varchar2,
    key  varchar2,
    sig  varchar2,
    alg  varchar2
) return boolean
as
language java name 'SignatureUtl.verify(java.lang.String, java.lang.String, java.lang.String, java.lang.String) return boolean';
/

create or replace function signatureutl_sign
(
    text varchar2,
    key  varchar2,
    alg  varchar2
) return varchar2
as
language java name 'SignatureUtl.sign(java.lang.String, java.lang.String, java.lang.String) return java.lang.String';
/
--
 */
public class SignatureUtl {
  /*
   * verify
   */
  public static boolean verify(String text, String key, String sig, String alg)
  throws Exception
  {
    byte[] data   = text.getBytes("UTF-8");          // plain text into bytes
    byte[] pkdata = Base64.getDecoder().decode(key); // PEM text key into DER
    byte[] dsig   = Base64.getDecoder().decode(sig); // Base64 signature into bytes
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PublicKey  publicKey  = keyFactory.generatePublic(new X509EncodedKeySpec(pkdata));
    Signature signature = Signature.getInstance(alg);
    signature.initVerify(publicKey);
    signature.update(data);
    return signature.verify(dsig);
  }
  /*
   * sign - privare key in PKCS#8
   */
  public static String sign(String text, String key, String alg)
  throws Exception
  {
    byte[] data   = text.getBytes("UTF-8");           // plain text into bytes
    byte[] pkdata = Base64.getDecoder().decode(key);  // PEM text key into DER
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(pkdata));
    Signature signature = Signature.getInstance(alg);
    signature.initSign(privateKey);
    signature.update(data);
    byte[] bytes = signature.sign();
    return Base64.getEncoder().encodeToString(bytes);
  }
}