[GitHub] [spark] dongjoon-hyun commented on a change in pull request #32801: [SPARK-12567][SQL] Add aes_encrypt and aes_decrypt builtin functions

2021-06-26 Thread GitBox


dongjoon-hyun commented on a change in pull request #32801:
URL: https://github.com/apache/spark/pull/32801#discussion_r659262486



##
File path: 
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/FunctionRegistry.scala
##
@@ -622,6 +622,8 @@ object FunctionRegistry {
 expression[Sha1]("sha", true),
 expression[Sha1]("sha1"),
 expression[Sha2]("sha2"),
+expression[AesEncrypt]("aes_encrypt"),
+expression[AesDecrypt]("aes_decrypt"),

Review comment:
   This seems to be supported by MySQL and Oracle, right? Could you mention 
it in the PR description?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: reviews-unsubscr...@spark.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org



-
To unsubscribe, e-mail: reviews-unsubscr...@spark.apache.org
For additional commands, e-mail: reviews-h...@spark.apache.org



[GitHub] [spark] dongjoon-hyun commented on a change in pull request #32801: [SPARK-12567][SQL] Add aes_encrypt and aes_decrypt builtin functions

2021-06-26 Thread GitBox


dongjoon-hyun commented on a change in pull request #32801:
URL: https://github.com/apache/spark/pull/32801#discussion_r659262138



##
File path: 
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/misc.scala
##
@@ -301,3 +305,137 @@ case class CurrentUser() extends LeafExpression with 
Unevaluable {
   override def prettyName: String = "current_user"
   final override val nodePatterns: Seq[TreePattern] = Seq(CURRENT_LIKE)
 }
+
+/**
+ * The base implementation for AES encryption and decryption.
+ */
+abstract class AesBase(left: Expression, right: Expression)
+  extends BinaryExpression with ImplicitCastInputTypes with NullIntolerant 
with Serializable {
+
+  override def dataType: DataType = BinaryType
+  override def nullable: Boolean = true
+  override def inputTypes: Seq[DataType] = Seq(BinaryType, BinaryType)
+  protected val cipherMode: Int
+
+  @transient lazy protected val cipher: Cipher = try {
+Cipher.getInstance("AES")
+  } catch {
+case e @ (_: NoSuchPaddingException | _: NoSuchAlgorithmException) =>
+  throw new RuntimeException(e)
+  }
+
+  protected override def nullSafeEval(input1: Any, input2: Any): Any = {
+val input = input1.asInstanceOf[Array[Byte]]
+val key = input2.asInstanceOf[Array[Byte]]
+val inputLength = input.length
+val keyLength = key.length
+val secretKey = keyLength match {
+  case 16 | 24 | 32 => new SecretKeySpec(key, 0, keyLength, "AES")
+  case _ => null
+}
+
+if (secretKey == null) {
+  return null
+}
+
+try {
+  cipher.init(cipherMode, secretKey)
+  cipher.doFinal(input, 0, inputLength)
+} catch {
+  case _: GeneralSecurityException =>
+null
+}
+  }
+
+  override def doGenCode(ctx: CodegenContext, ev: ExprCode): ExprCode = {
+val inputLength = ctx.freshName("inputLength")
+val keyLength = ctx.freshName("keyLength")
+val secretKey = ctx.freshName("secretKey")
+val cipher = ctx.addMutableState("javax.crypto.Cipher", "cihper", v =>
+  s"""
+try {
+  $v = javax.crypto.Cipher.getInstance("AES");
+} catch (javax.crypto.NoSuchPaddingException e) {
+  throw new RuntimeException(e);
+} catch (java.security.NoSuchAlgorithmException e) {
+  throw new RuntimeException(e);
+}""")
+
+nullSafeCodeGen(ctx, ev, (eval1, eval2) => {
+  s"""
+int $inputLength = $eval1.length;
+int $keyLength = $eval2.length;
+javax.crypto.SecretKey $secretKey = null;
+if ($keyLength == 16 || $keyLength == 24 || $keyLength == 32) {
+  $secretKey = new javax.crypto.spec.SecretKeySpec($eval2, 0, 
$keyLength, "AES");
+} else {
+  ${ev.isNull} = true;
+}
+if ($secretKey == null) {
+  ${ev.isNull} = true;
+} else {
+  try {
+$cipher.init($cipherMode, $secretKey);
+${ev.value} = $cipher.doFinal($eval1, 0, $inputLength);
+  } catch (java.security.GeneralSecurityException e) {
+${ev.isNull} = true;
+  }
+}
+   """
+})
+  }
+}
+
+/**
+ * A function that encrypts input using AES. Key lengths of 128, 192 or 256 
bits can be used.
+ * For versions prior to JDK 8u161, 192 and 256 bits keys can be used
+ * if Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy 
Files are installed.
+ * If either argument is NULL or the key length is not one of the permitted 
values,
+ * the return value is NULL.
+ */
+@ExpressionDescription(
+  usage = """
+_FUNC_(expr, key) - Returns a encrypted value of `expr` using AES.

Review comment:
   nit. `a` -> `an`?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: reviews-unsubscr...@spark.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org



-
To unsubscribe, e-mail: reviews-unsubscr...@spark.apache.org
For additional commands, e-mail: reviews-h...@spark.apache.org