PL/SQL中的RSA加密

目录

介绍

背景

使用代码

兴趣点


如何在Oracle 11g PL / SQL软件包(带有某些JAVA帮助器)中使用RSA公钥加密数据

介绍

最近,我需要使用提供的RSA公钥从Oracle PL / sQL包中加密某些信息,以便能够与以这种方式进行身份验证的Web服务进行通信。

在互联网上进行了一些研究之后,我找不到任何可行的解决方案(免费)。找到了许多概念、想法、零碎的解释或付费软件,但是花了比平常更多的时间和精力才能找到一个可行的解决方案,我必须自己动手完成大部分工作。

因此,我决定将其发布以供公众了解。

背景

首先,确保以正确的方式配置环境很重要:

1、您需要确保ORACLE DB已安装JAVA VM。您可以通过以下方式进行检查:

select comp_name, version, status from dba_registry;

如果不存在,则必须以SYS身份登录并执行以下操作:

SQL> @$ORACLE_HOME/javavm/install/initjvm.sql;

一旦安装了JavaVM,便一切就绪。

2、出于本文的目的,我们将使用公共密钥对密码进行加密,因此,它可以在另一端使用相应的私钥进行发送和解密。但是我们将需要:

  • 我们的密码(我们将使用password
  • 我们的公钥文件(我将其称为rsa.public

就我而言,我正在使用Oracle11g11.2.0.4

使用代码

我们需要了解的第一件事是,ORACLE不提供(在版本11g中)非对称密码学的库。DBMS_CRYPTO软件包将仅提供对称加密。

因此,我们需要创建自己的类来处理它。而且我们将需要使用Java来实现。创建或替换并编译名为rsa_cryptoJava源文件为:

import javax.crypto.*;
import java.security.spec.*; 
import java.security.*; //PublicKey

public class RSACrypto
{
  public static byte[] Encrypt(byte[] cert, byte[] data) 
         throws Throwable //NoSuchAlgorithmException, InvalidKeySpecException, 
                          //InvalidKeyException, IllegalBlockSizeException, 
                          //NoSuchPaddingException, BadPaddingException
  {
      byte[] encryptedData = null;
      try {

        //Generate Public Key with Cert
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(cert);
        PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
        
        //Encrypt
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");  
        cipher.init(Cipher.ENCRYPT_MODE, pubKey); 
        encryptedData = cipher.doFinal(data);

        return encryptedData;
     } catch (Exception e) {
        System.out.println(  "Unexpected error - " + e.getMessage());
        encryptedData = e.getMessage().getBytes();
        throw e;
     }
  }
}

我们的函数将接收2个字节的数组(证书内容和要加密的数据),并将返回带有加密的Data的字节数组。

我们将创建我们的包,并在其主体内声明以下private函数:

function rsa_encrypt(cert raw, data raw) return raw
     AS LANGUAGE JAVA
      NAME 'RSACrypto.Encrypt(byte[], byte[]) return byte[]';

然后我们将拥有我们的login函数,该函数将通过以下方式使用我们的JAVA函数:

c_certini              constant varchar2(50) := '-----BEGIN PUBLIC KEY-----';
c_certend              constant varchar2(50) := '-----END PUBLIC KEY-----';
c_dirname              constant varchar2(255) := 'DIRX';
c_key_filename         constant varchar2(255) := 'rsa.public';

function login return number is
     
      passpost  raw(1024);
      res    varchar2(1024);
      
      v_fexist  boolean;
      v_flen    number;
      v_bsize   binary_integer;
      v_key    utl_file.file_type;
      v_cert   raw(2048);
      v_buffer varchar2(2048);
     
  begin
            
      -- Check and Read Certificate
      utl_file.fgetattr(c_dirname, c_key_filename, v_fexist, v_flen, v_bsize);
      if not v_fexist then
         dbms_output.put_line(c_dirname || '/' || c_key_filename || ' Not Found.');
         return -3;
      end if;
      v_key := utl_file.fopen(c_dirname, c_key_filename,'R');
      utl_file.get_raw(v_key,v_cert,v_flen);
      utl_file.fclose(v_key);
      dbms_output.put_line('Cert Read: ' || utl_raw.cast_to_varchar2(v_cert));
      v_buffer := utl_raw.cast_to_varchar2(v_cert);      
      
      -- Strip beginning and end.
      v_buffer := replace(v_buffer,c_certini,'');
      v_buffer := replace(v_buffer,c_certend,'');
      v_cert := utl_encode.base64_decode(utl_raw.cast_to_raw(v_buffer));
      dbms_output.put_line('Cert Strip: [' || v_buffer || ']');
      
      --Call to JAVA function
      begin
             passpost:=rsa_encrypt(v_cert,utl_raw.cast_to_raw('Password'));
      exception when others then
             dbms_output.put_line('Cannot encrypt ' || SQLERRM);  
             return -4;
      end;
      if passpost is null then
         return -2;
      end if;
      res:= utl_raw.cast_to_varchar2(utl_encode.base64_encode(passpost));
      dbms_output.put_line('Encrypted Signature: ' || res);     
        
      return 0;
      
  end;

兴趣点

基本上,我们:打开文件,读取文件内容,并将其传递给Java函数Base64DecodedJava函数将使用接收到的Content创建一个公共密钥,并用它加密数据并返回它。我们将对返回的数据进行64位编码,然后将其用于我们需要的任何其他内容。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值