2017-07-31 120 views
0

我已经写了一个类来解密我们公司的客户ID和一个密钥。解密算法是DES。apache drill执行udf 2次,答案不是我想要的

然后,我重新考虑了下面的代码,并将算法从DES更改为AES,但是当我运行select函数时,解密将运行两次。首先得到正确的结果,然后第二个结果是错误的。 (所以最后的结果是错误的)

我在这里列出我的代码:

package org.apache.drill.exec.fn.impl; 

import com.google.common.base.Charsets; 
import io.netty.buffer.DrillBuf; 
import org.apache.commons.codec.DecoderException; 
import org.apache.commons.codec.net.BCodec; 
import org.apache.drill.exec.expr.DrillSimpleFunc; 
import org.apache.drill.exec.expr.annotations.FunctionTemplate; 
import org.apache.drill.exec.expr.annotations.Output; 
import org.apache.drill.exec.expr.annotations.Param; 
import org.apache.drill.exec.expr.annotations.Workspace; 
import org.apache.drill.exec.expr.holders.VarCharHolder; 

import javax.crypto.*; 
import javax.crypto.spec.DESKeySpec; 
import javax.crypto.spec.SecretKeySpec; 
import javax.inject.Inject; 

@functiontemplate(
name = "decode_cid", 
scope = FunctionTemplate.FunctionScope.SIMPLE, 
nulls = FunctionTemplate.NullHandling.NULL_IF_NULL 
) 

public class DecodeCidFunction implements DrillSimpleFunc { 

@Param 
VarCharHolder raw_input; 
// @Param 
// VarCharHolder raw_key; 

@Output 
VarCharHolder out; 

@Inject 
DrillBuf buffer; 
// @workspace 
// KeyGenerator keygenerator; 

@Workspace 
SecretKey myDesKey; 

@Workspace 
Cipher desCipher; 

@Workspace 
BCodec bCodec; 

@Override 
public void setup() { 
    try { 
     String key = "this is a secret"; 
     javax.crypto.SecretKeyFactory factory = javax.crypto.SecretKeyFactory.getInstance("DES"); 
     myDesKey = factory.generateSecret(new javax.crypto.spec.DESKeySpec(key.getBytes())) ; 
     System.out.println("myDesKey = "+myDesKey.toString()); 
     // Create the cipher 
     desCipher = Cipher.getInstance("DES"); 

     // Initialize the cipher for encryption 
     desCipher.init(Cipher.DECRYPT_MODE, myDesKey); 

     bCodec = new BCodec("UTF-8"); 

    } catch(Exception e) { 
     System.out.println("may i come here"); 
     e.printStackTrace(); 
    } 
} 

@Override 
public void eval() { 
    String input = org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.toStringFromUTF8(raw_input.start, raw_input.end, raw_input.buffer); 
    String output = ""; 
    System.out.println("input = " + input); 
    if (input.startsWith("=?")) 
    { 
     try{ 
      output = bCodec.decode(input); 
     }catch(Exception e){ 
      System.out.println("find an error :" +e.toString()); 
      output = ""; 
     } 
    }else{ 
     byte[] bts = new byte[input.length()/2]; 
     for (int i = 0; i < bts.length; i++) { 
      bts[i] = (byte) Integer.parseInt(input.substring(2*i, 2*i+2), 16); 
     } 
     System.out.println("bts = " +bts.toString()); 
     try{ 
      byte[] decodedString = desCipher.doFinal(bts) ; 
      output = new String(decodedString, "utf-8"); 
     }catch(Exception e){ 
      System.out.println("i come here " + e.toString()); 
      output=""; 
     } 
    } 
    System.out.println("output = " + output); 
    out.buffer = buffer; 
    out.start = 0; 
    out.end = output.getBytes().length; 
    buffer.setBytes(0, output.getBytes()); 
} 
} 

输出:

而我选择查询如下:+1:

0: jdbc:drill:zk=local> select decode_cid('A849333D2713FAFEA10780AD02139B29') from (values(1)); 
myDesKey = [email protected] 
input = A849333D2713FAFEA10780AD02139B29 
bts = [[email protected] 
output = 20138690 
myDesKey = [email protected] 
input = A849333D2713FAFEA10780AD02139B29 
bts = [[email protected] 
    I come here javax.crypto.BadPaddingException: Given final block not properly padded 
output = 
+---------+ 
| EXPR$0 | 
+---------+ 
| | 
+---------+ 
1 row selected (3.075 seconds) 

你可以看到第一个输出是正确的,但是第二个是空的,null不是我想要的。我想知道它为什么运行两次?

+0

我尽我所能来解决语法和解释你如何试图重新因子代码从DES解密AES解密转换。 – rjdkolb

+0

非常感谢!我真的不知道为什么它执行了2次,并且在第一次执行之后密钥已经改变,并且第一次执行的结果是我想要的 – zilaiye1988

回答

1
+0

你说的没错,虽然drill已经实现了一些算法,des描述没有实现,我想实现一个自定义算法是基于我们公司的业务,我只是想知道为什么它执行2次,我发现在第一次执行后更改了密钥,密钥发生了什么,我只想知道它为什么执行2次,它只能执行一次吗? – zilaiye1988

+0

我已经尝试了您的代码,并从输出中看到错误是两次(不像您的示例中,它只有一次):'myDesKey = [email protected] input = A849333D2713FAFEA10780AD02139B29 BTS = [B @ 3422de25 我来这里javax.crypto.BadPaddingException:给定最终块未正确填充 输出= myDesKey = [email protected] 输入= A849333D2713FAFEA10780AD02139B29 BTS = [B @ 7222c376 我来这里javax.crypto.BadPaddingException:鉴于最终块没有正确填充 输出=' –

+0

您看到不同结果的原因是因为如果您对功能代码进行任何更改,则需要重建项目。由于Drill使用在构建期间添加到目标类位置的udf源代码。 –