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