Apache Drill выполнить UDF 2 раза, и ответ не хочу
Я написал класс для расшифровки идентификатора клиента нашей компании с секретным ключом. Алгоритм дешифрования - DES.
Затем я повторно проанализировал приведенный ниже код и изменил алгоритм с DES на AES, но когда я запускаю функцию выбора, расшифровка выполняется дважды. Сначала с правильным результатом, а затем второй результат неверен. (Итоговый результат неверный)
Я перечислю свой код здесь:
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 = com.sun.crypto.provider.DESKey@183d7
input = A849333D2713FAFEA10780AD02139B29
bts = [B@22f4128e
output = 20138690
myDesKey = com.sun.crypto.provider.DESKey@18301
input = A849333D2713FAFEA10780AD02139B29
bts = [B@7a69714
I come here javax.crypto.BadPaddingException: Given final block not properly padded
output =
+---------+
| EXPR$0 |
+---------+
| |
+---------+
1 row selected (3.075 seconds)
Вы можете видеть, что первый вывод правильный, но второй - ноль, ноль - не то, что я хочу. Я хочу знать, почему он работает два раза?
1 ответ
С 1.11 Apache Drill включает в себя реализацию некоторых криптографических функций, включая AES [1]. Ссылка на исходный код - https://github.com/apache/drill/blob/master/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/CryptoFunctions.java#L272-L384
[1] https://drill.apache.org/blog/2017/07/31/drill-1.11-released/