This is an automated email from the ASF dual-hosted git repository.

GGraziadei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/storm.git


The following commit(s) were added to refs/heads/master by this push:
     new 796492816 Remove deprecated BlowfishTupleSerializer (#8994) (#9167)
796492816 is described below

commit 7964928167cdede819eee3bf323ac2c9d48d9560
Author: Mohit Nehete <[email protected]>
AuthorDate: Sat Oct 24 19:36:01 2026 +0530

    Remove deprecated BlowfishTupleSerializer (#8994) (#9167)
---
 docs/SECURITY.md                                   |   2 +-
 .../serialization/BlowfishTupleSerializer.java     | 113 ---------------------
 .../serialization/BlowfishTupleSerializerTest.java | 107 -------------------
 .../serialization/SerializationFactoryTest.java    |  20 +++-
 .../org/apache/storm/daemon/nimbus/Nimbus.java     |  13 +--
 .../daemon/nimbus/NimbusGetTopologyConfTest.java   |   7 +-
 .../nimbus/NimbusGetTopologyPageInfoTest.java      |   5 +-
 7 files changed, 28 insertions(+), 239 deletions(-)

diff --git a/docs/SECURITY.md b/docs/SECURITY.md
index 6ab9f96c0..a46be6a49 100644
--- a/docs/SECURITY.md
+++ b/docs/SECURITY.md
@@ -680,7 +680,7 @@ The size limits need a caveat. `maxbytes` counts stream 
bytes per object, not pe
 
 An invalid pattern is rejected when the topology is submitted, and otherwise 
fails worker startup.
 
-For tuple encryption, use TLS-based transport encryption 
(`storm.messaging.netty.tls.enable`) instead of the deprecated 
`BlowfishTupleSerializer`, which uses a 64-bit block cipher vulnerable to 
birthday attacks.
+For tuple encryption, use TLS-based transport encryption 
(`storm.messaging.netty.tls.enable`). The legacy `BlowfishTupleSerializer` has 
been removed because it uses a 64-bit block cipher vulnerable to birthday 
attacks.
 
 ### Log Cleanup
 The Logviewer daemon now is also responsible for cleaning up old log files for 
dead topologies.
diff --git 
a/storm-client/src/jvm/org/apache/storm/security/serialization/BlowfishTupleSerializer.java
 
b/storm-client/src/jvm/org/apache/storm/security/serialization/BlowfishTupleSerializer.java
deleted file mode 100644
index 791e97eb6..000000000
--- 
a/storm-client/src/jvm/org/apache/storm/security/serialization/BlowfishTupleSerializer.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.  The 
ASF licenses this file to you under the Apache License, Version
- * 2.0 (the "License"); you may not use this file except in compliance with 
the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
See the License for the specific language governing permissions
- * and limitations under the License.
- */
-
-package org.apache.storm.security.serialization;
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import com.esotericsoftware.kryo.serializers.BlowfishSerializer;
-import java.util.Map;
-import javax.crypto.KeyGenerator;
-import javax.crypto.SecretKey;
-import org.apache.storm.Config;
-import org.apache.storm.serialization.types.ListDelegateSerializer;
-import org.apache.storm.shade.org.apache.commons.codec.DecoderException;
-import org.apache.storm.shade.org.apache.commons.codec.binary.Hex;
-import org.apache.storm.utils.ListDelegate;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Apply Blowfish encryption for tuple communication to bolts.
- *
- * @deprecated since 2.8.6. Blowfish uses a 64-bit block size which is 
vulnerable to birthday
- *     attacks (Sweet32).
- *     Use TLS-based transport encryption instead (see 
storm.messaging.netty.tls.enable).
- */
-@Deprecated(since = "2.8.6", forRemoval = true)
-public class BlowfishTupleSerializer extends Serializer<ListDelegate> {
-    /**
-     * The secret key (if any) for data encryption by blowfish payload 
serialization factory
-     * (BlowfishSerializationFactory). You should use
-     * in via:
-     *
-     * <p>```storm -c topology.tuple.serializer.blowfish.key=YOURKEY -c
-     * topology.tuple.serializer=org.apache.storm.security.serialization
-     * .BlowfishTupleSerializer
-     * jar ...```
-     */
-    public static final String SECRET_KEY = 
"topology.tuple.serializer.blowfish.key";
-    private static final Logger LOG = 
LoggerFactory.getLogger(BlowfishTupleSerializer.class);
-    private BlowfishSerializer serializer;
-
-    public BlowfishTupleSerializer(Kryo unused, Map<String, Object> topoConf) {
-        String encryptionkey;
-        try {
-            encryptionkey = (String) topoConf.get(SECRET_KEY);
-            LOG.warn("BlowfishTupleSerializer is deprecated and will be 
removed in a future "
-                    + "release. "
-                    + "Blowfish uses a 64-bit block size which is vulnerable 
to birthday attacks "
-                    + "(Sweet32). "
-                    + "Use TLS-based transport encryption instead "
-                    + "(storm.messaging.netty.tls.enable).");
-
-            byte[] bytes;
-            if (encryptionkey != null) {
-                bytes = Hex.decodeHex(encryptionkey.toCharArray());
-            } else {
-                // try to use zookeeper secret
-                String payload = (String) topoConf
-                        .get(Config.STORM_ZOOKEEPER_TOPOLOGY_AUTH_PAYLOAD);
-                if (payload != null) {
-                    LOG.debug("{} is not present. Use {} as Blowfish 
encryption key", SECRET_KEY,
-                            Config.STORM_ZOOKEEPER_TOPOLOGY_AUTH_PAYLOAD);
-                    bytes = payload.getBytes();
-                } else {
-                    throw new RuntimeException("Blowfish encryption key not 
specified");
-                }
-            }
-            serializer = new BlowfishSerializer(new ListDelegateSerializer(), 
bytes);
-        } catch (DecoderException ex) {
-            throw new RuntimeException("Blowfish encryption key invalid", ex);
-        }
-    }
-
-    /**
-     * Produce a blowfish key to be used in "Storm jar" command.
-     */
-    public static void main(String[] args) {
-        try {
-            KeyGenerator kgen = KeyGenerator.getInstance("Blowfish");
-            kgen.init(256);
-            SecretKey skey = kgen.generateKey();
-            byte[] raw = skey.getEncoded();
-            String keyString = new String(Hex.encodeHex(raw));
-            System.out.println("storm -c " + SECRET_KEY
-                    + "=" + keyString + " -c " + 
Config.TOPOLOGY_TUPLE_SERIALIZER
-                    + "=" + BlowfishTupleSerializer.class.getName() + " ...");
-        } catch (Exception ex) {
-            LOG.error(ex.getMessage());
-        }
-    }
-
-    @Override
-    public void write(Kryo kryo, Output output, ListDelegate object) {
-        kryo.writeObject(output, object, serializer);
-    }
-
-    @Override
-    public ListDelegate read(Kryo kryo, Input input, Class<? extends 
ListDelegate> type) {
-        return kryo.readObject(input, ListDelegate.class, serializer);
-    }
-}
diff --git 
a/storm-client/test/jvm/org/apache/storm/security/serialization/BlowfishTupleSerializerTest.java
 
b/storm-client/test/jvm/org/apache/storm/security/serialization/BlowfishTupleSerializerTest.java
deleted file mode 100644
index b1fdfb050..000000000
--- 
a/storm-client/test/jvm/org/apache/storm/security/serialization/BlowfishTupleSerializerTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.  The 
ASF licenses this file to you under the Apache License, Version
- * 2.0 (the "License"); you may not use this file except in compliance with 
the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
See the License for the specific language governing permissions
- * and limitations under the License.
- */
-
-package org.apache.storm.security.serialization;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import org.apache.storm.Config;
-import org.apache.storm.shade.com.google.common.base.Joiner;
-import org.apache.storm.shade.com.google.common.collect.ImmutableMap;
-import org.apache.storm.utils.ListDelegate;
-import org.junit.jupiter.api.Test;
-
-public class BlowfishTupleSerializerTest {
-
-    /**
-     * Throws RuntimeException when no encryption key is given.
-     */
-    @Test
-    public void testConstructorThrowsOnNullKey() {
-        assertThrows(RuntimeException.class, () -> new 
BlowfishTupleSerializer(null,
-                new HashMap<>()));
-    }
-
-    /**
-     * Throws RuntimeException when an invalid encryption key is given.
-     */
-    @Test
-    public void testConstructorThrowsOnInvalidKey() {
-        // The encryption key must be hexadecimal.
-        assertThrows(RuntimeException.class,
-                () -> new BlowfishTupleSerializer(null, ImmutableMap
-                .of(BlowfishTupleSerializer.SECRET_KEY, "0123456789abcdefg")));
-    }
-
-    /**
-     * Test using {@link
-     * 
org.apache.storm.security.serialization.BlowfishTupleSerializer#SECRET_KEY}.
-     */
-    @Test
-    public void testUseBlowfishKey() {
-        String arbitraryKey = "7dd6fb3203878381b08f9c89d25ed105";
-        Map<String, Object> topoConf = 
ImmutableMap.of(BlowfishTupleSerializer.SECRET_KEY,
-                arbitraryKey);
-        testEncryptsAndDecryptsMessage(topoConf);
-    }
-
-    /**
-     * Test using {@link 
org.apache.storm.Config#STORM_ZOOKEEPER_TOPOLOGY_AUTH_PAYLOAD}
-     * when {@link 
org.apache.storm.security.serialization.BlowfishTupleSerializer#SECRET_KEY} is
-     * not present.
-     */
-    @Test
-    public void testUseZookeeperSecret() {
-        Map<String, Object> topoConf = 
ImmutableMap.of(Config.STORM_ZOOKEEPER_TOPOLOGY_AUTH_PAYLOAD,
-                "user:password");
-        testEncryptsAndDecryptsMessage(topoConf);
-    }
-
-    /**
-     * Reads a string encrypted by another instance with a shared key.
-     */
-    private void testEncryptsAndDecryptsMessage(Map<String, Object> topoConf) {
-        String testText =
-                "Tetraodontidae is a family of primarily marine and estuarine 
fish of the order"
-                + " Tetraodontiformes. The family includes many familiar 
species, which are"
-                + " variously called pufferfish, puffers, balloonfish, 
blowfish, bubblefish,"
-                + " globefish, swellfish, toadfish, toadies, honey toads, 
sugar toads, and sea"
-                + " squab.[1] They are morphologically similar to the closely 
related"
-                + " porcupinefish, which have large external spines (unlike 
the thinner, hidden"
-                + " spines of Tetraodontidae, which are only visible when the 
fish has puffed up)."
-                + " The scientific name refers to the four large teeth, fused 
into an upper and"
-                + " lower plate, which are used for crushing the shells of 
crustaceans and"
-                + " mollusks, their natural prey.";
-        Kryo kryo = new Kryo();
-        kryo.setRegistrationRequired(false);
-        BlowfishTupleSerializer writerBTS = new BlowfishTupleSerializer(null, 
topoConf);
-        BlowfishTupleSerializer readerBTS = new BlowfishTupleSerializer(null, 
topoConf);
-        int bufferSize = 1024;
-        Output output = new Output(bufferSize, bufferSize);
-        Input input = new Input(bufferSize);
-        String[] stringList = testText.split(" ");
-        ListDelegate delegate = new ListDelegate();
-        delegate.addAll(Arrays.asList(stringList));
-
-        writerBTS.write(kryo, output, delegate);
-        input.setBuffer(output.getBuffer());
-        ListDelegate outDelegate = readerBTS.read(kryo, input, 
ListDelegate.class);
-        assertEquals(testText, Joiner.on(" ").join(outDelegate.toArray()));
-    }
-}
diff --git 
a/storm-client/test/jvm/org/apache/storm/serialization/SerializationFactoryTest.java
 
b/storm-client/test/jvm/org/apache/storm/serialization/SerializationFactoryTest.java
index 82a5d3073..b86e994c7 100644
--- 
a/storm-client/test/jvm/org/apache/storm/serialization/SerializationFactoryTest.java
+++ 
b/storm-client/test/jvm/org/apache/storm/serialization/SerializationFactoryTest.java
@@ -17,9 +17,11 @@ import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
 import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.Serializer;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
 import java.util.Map;
 import org.apache.storm.Config;
-import org.apache.storm.security.serialization.BlowfishTupleSerializer;
 import org.apache.storm.testing.TestWordSpout;
 import org.apache.storm.topology.TopologyBuilder;
 import org.apache.storm.utils.ListDelegate;
@@ -48,14 +50,11 @@ public class SerializationFactoryTest {
 
     @Test
     public void test_registers_when_valid_class_name() {
-        Class arbitraryClass = BlowfishTupleSerializer.class;
-        String secretKey = "0123456789abcdef";
+        Class arbitraryClass = MockTupleSerializer.class;
         Map<String, Object> conf = Utils.readDefaultConfig();
         conf.put(Config.TOPOLOGY_TUPLE_SERIALIZER, arbitraryClass.getName());
-        conf.put(BlowfishTupleSerializer.SECRET_KEY, secretKey);
         Kryo kryo = SerializationFactory.getKryo(conf);
         assertEquals(arbitraryClass, 
kryo.getSerializer(ListDelegate.class).getClass());
-
     }
 
     @Test
@@ -93,4 +92,15 @@ public class SerializationFactoryTest {
     public static class MockSerObject {
     }
 
+    public static class MockTupleSerializer extends Serializer<ListDelegate> {
+        @Override
+        public void write(Kryo kryo, Output output, ListDelegate object) {
+        }
+
+        @Override
+        public ListDelegate read(Kryo kryo, Input input, Class<? extends 
ListDelegate> type) {
+            return null;
+        }
+    }
+
 }
diff --git 
a/storm-server/src/main/java/org/apache/storm/daemon/nimbus/Nimbus.java 
b/storm-server/src/main/java/org/apache/storm/daemon/nimbus/Nimbus.java
index 9e184feb6..9a7d6beda 100644
--- a/storm-server/src/main/java/org/apache/storm/daemon/nimbus/Nimbus.java
+++ b/storm-server/src/main/java/org/apache/storm/daemon/nimbus/Nimbus.java
@@ -200,7 +200,6 @@ import org.apache.storm.security.auth.ReqContext;
 import org.apache.storm.security.auth.ThriftConnectionType;
 import org.apache.storm.security.auth.ThriftServer;
 import org.apache.storm.security.auth.workertoken.WorkerTokenManager;
-import org.apache.storm.security.serialization.BlowfishTupleSerializer;
 import org.apache.storm.shade.com.google.common.annotations.VisibleForTesting;
 import org.apache.storm.shade.com.google.common.base.Strings;
 import org.apache.storm.shade.com.google.common.collect.ImmutableMap;
@@ -806,20 +805,22 @@ public class Nimbus implements Iface, Shutdownable, 
DaemonCommon {
         return tc.readTopology(topoId, NIMBUS_SUBJECT);
     }
 
+    @VisibleForTesting
+    static final String LEGACY_BLOWFISH_SECRET_KEY = 
"topology.tuple.serializer.blowfish.key";
+
     /**
      * Mask the credential values in a config map that is about to be 
serialized to a client. Nimbus serves config over
      * several read-only operations, and a caller authorized for those is not 
necessarily authorized to hold the cluster's
-     * or the topology's secrets. This covers what {@link 
ConfigUtils#maskCredentials(Map)} covers, plus the Blowfish
-     * tuple-serializer key, whose constant lives outside the config classes 
so the annotation scan cannot see it and
-     * whose name matches no credential pattern.
+     * or the topology's secrets. This covers what {@link 
ConfigUtils#maskCredentials(Map)} covers, plus the legacy Blowfish
+     * tuple-serializer key, so that legacy stored configs do not leak the key.
      *
      * @param conf the config about to be served
      * @return a copy of the config with credential values replaced
      */
     private static Map<String, Object> maskCredentialsForApi(Map<String, 
Object> conf) {
         Map<String, Object> masked = new 
HashMap<>(ConfigUtils.maskCredentials(conf));
-        if (masked.get(BlowfishTupleSerializer.SECRET_KEY) instanceof String) {
-            masked.put(BlowfishTupleSerializer.SECRET_KEY, "*****");
+        if (masked.get(LEGACY_BLOWFISH_SECRET_KEY) instanceof String) {
+            masked.put(LEGACY_BLOWFISH_SECRET_KEY, "*****");
         }
         return masked;
     }
diff --git 
a/storm-server/src/test/java/org/apache/storm/daemon/nimbus/NimbusGetTopologyConfTest.java
 
b/storm-server/src/test/java/org/apache/storm/daemon/nimbus/NimbusGetTopologyConfTest.java
index fae4ad566..0121527ad 100644
--- 
a/storm-server/src/test/java/org/apache/storm/daemon/nimbus/NimbusGetTopologyConfTest.java
+++ 
b/storm-server/src/test/java/org/apache/storm/daemon/nimbus/NimbusGetTopologyConfTest.java
@@ -29,7 +29,6 @@ import org.apache.storm.blobstore.BlobStore;
 import org.apache.storm.cluster.IStormClusterState;
 import net.minidev.json.JSONValue;
 
-import org.apache.storm.security.serialization.BlowfishTupleSerializer;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentMatchers;
 import org.mockito.Mockito;
@@ -56,7 +55,7 @@ public class NimbusGetTopologyConfTest {
         Map<String, Object> storedConf = new HashMap<>();
         storedConf.put(Config.TOPOLOGY_NAME, TOPO_NAME);
         storedConf.put(Config.STORM_ZOOKEEPER_TOPOLOGY_AUTH_PAYLOAD, 
"topology-zk-secret");
-        storedConf.put(BlowfishTupleSerializer.SECRET_KEY, "0123456789abcdef");
+        storedConf.put(Nimbus.LEGACY_BLOWFISH_SECRET_KEY, "0123456789abcdef");
         storedConf.put(Config.TOPOLOGY_WORKERS, 3);
 
         try (LocalCluster cluster = new LocalCluster.Builder()
@@ -77,7 +76,7 @@ public class NimbusGetTopologyConfTest {
 
             assertEquals(MASKED, 
served.get(Config.STORM_ZOOKEEPER_TOPOLOGY_AUTH_PAYLOAD),
                 "the ZooKeeper auth payload should be masked");
-            assertEquals(MASKED, 
served.get(BlowfishTupleSerializer.SECRET_KEY),
+            assertEquals(MASKED, served.get(Nimbus.LEGACY_BLOWFISH_SECRET_KEY),
                 "the tuple serializer key should be masked");
 
             assertEquals(TOPO_NAME, served.get(Config.TOPOLOGY_NAME));
@@ -85,7 +84,7 @@ public class NimbusGetTopologyConfTest {
 
             assertEquals("topology-zk-secret", 
storedConf.get(Config.STORM_ZOOKEEPER_TOPOLOGY_AUTH_PAYLOAD),
                 "the stored conf should keep its own values");
-            assertEquals("0123456789abcdef", 
storedConf.get(BlowfishTupleSerializer.SECRET_KEY),
+            assertEquals("0123456789abcdef", 
storedConf.get(Nimbus.LEGACY_BLOWFISH_SECRET_KEY),
                 "the stored conf should keep its own values");
         }
     }
diff --git 
a/storm-server/src/test/java/org/apache/storm/daemon/nimbus/NimbusGetTopologyPageInfoTest.java
 
b/storm-server/src/test/java/org/apache/storm/daemon/nimbus/NimbusGetTopologyPageInfoTest.java
index c9bf4d2c5..700bca0bd 100644
--- 
a/storm-server/src/test/java/org/apache/storm/daemon/nimbus/NimbusGetTopologyPageInfoTest.java
+++ 
b/storm-server/src/test/java/org/apache/storm/daemon/nimbus/NimbusGetTopologyPageInfoTest.java
@@ -33,7 +33,6 @@ import org.apache.storm.generated.StormTopology;
 import org.apache.storm.generated.TopologyPageInfo;
 import org.apache.storm.generated.TopologyStatus;
 import 
org.apache.storm.scheduler.resource.TestUtilsForResourceAwareScheduler.TestSpout;
-import org.apache.storm.security.serialization.BlowfishTupleSerializer;
 import org.apache.storm.topology.TopologyBuilder;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentMatchers;
@@ -76,7 +75,7 @@ public class NimbusGetTopologyPageInfoTest {
         topoConf.put(Config.TOPOLOGY_EVENTLOGGER_EXECUTORS, 0);
         topoConf.put(Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS, 30);
         topoConf.put(Config.STORM_ZOOKEEPER_TOPOLOGY_AUTH_PAYLOAD, 
"topology-zk-secret");
-        topoConf.put(BlowfishTupleSerializer.SECRET_KEY, "0123456789abcdef");
+        topoConf.put(Nimbus.LEGACY_BLOWFISH_SECRET_KEY, "0123456789abcdef");
         return topoConf;
     }
 
@@ -137,7 +136,7 @@ public class NimbusGetTopologyPageInfoTest {
             // topology-side credentials, masked on getTopologyConf and 
equally reachable here
             assertEquals(MASKED, 
served.get(Config.STORM_ZOOKEEPER_TOPOLOGY_AUTH_PAYLOAD),
                 "the topology ZooKeeper auth payload should be masked");
-            assertEquals(MASKED, 
served.get(BlowfishTupleSerializer.SECRET_KEY),
+            assertEquals(MASKED, served.get(Nimbus.LEGACY_BLOWFISH_SECRET_KEY),
                 "the tuple serializer key should be masked");
 
             // values that carry no credential are served untouched

Reply via email to