From: Lucas C.S. <lucascs@protonmail.com>
Subject: [PATCH] components/web_package: keep Signed Web Bundle parsing and verification in C++, not Crubit

Revert of upstream e85da0b2f2dc ("Migrate Web Bundle integrity block parser
to dedicated Rust crate") and b2c9d9c61c9f ("Migrate Signed Web Bundle
signature verification to Rust crate"), both 2026-08-24, which landed in
M154.

Together they moved the integrity block parser and the Ed25519 / ECDSA
P-256 signature checks into
//components/web_package/signed_web_bundles/rust and exposed that crate to
C++ through a Crubit `cpp_api_from_rust` binding, which //components/
web_package depends on unconditionally.  `cpp_api_from_rust` only exists
when `enable_cpp_api_from_rust` is true, and //build/config/rust.gni turns
it false whenever `rust_sysroot_absolute` is set: Crubit needs a
cc_bindings_from_rs built against the very rustc in use plus a Rust stdlib
compiled by Chromium itself, and neither exists with a system toolchain.
With a system Rust sysroot gn therefore never defines
`signed_web_bundles_rust_bindings`, and `gn gen` dies:

  ERROR Unresolved dependencies.
  //components/web_package:web_package(...)
    needs //components/web_package/signed_web_bundles/rust:signed_web_bundles_rust_bindings(...)

This restores the M153 C++ implementation, which is what the two commits
replaced -- there is no C++ fallback left in M154 to gate on.  Only these
two commits are reverted: 06e93d8f12a0, which touched
identity_validator.{h,cc} after them, is disjoint and stays.

Same reachability as chromium-153-revert-font-format-crubit.patch: applied
only with USE=-bundled-toolchain; with the bundled toolchain upstream's
Crubit path works as-is.  Drop this patch once the overlay builds Crubit
for the system toolchain, or upstream gates the dependency on
`enable_cpp_api_from_rust`.

M156 split //components/web_package into `*_headers` and `*_rust_impl`
source sets; the three `signed_web_bundles_rust_*` dependencies moved with
the sources that use them, and the BUILD.gn hunks follow them there.  M156
also moved the Web Bundle parser itself to a second Crubit crate; that is
reverted separately by chromium-156-revert-web-bundle-parser-crubit.patch,
applied after this one.
diff --git a/components/web_package/BUILD.gn b/components/web_package/BUILD.gn
--- a/components/web_package/BUILD.gn
+++ b/components/web_package/BUILD.gn
@@ -52,7 +52,6 @@
     "//components/cbor",
     "//components/web_package/mojom",
     "//components/web_package/rust:web_package_rust_bindings",
-    "//components/web_package/signed_web_bundles/rust:signed_web_bundles_rust_bindings",
     "//mojo/public/cpp/bindings",
     "//net",
     "//services/network/public/mojom",
@@ -115,7 +114,6 @@
   deps = [
     ":mojom_mapped_types_headers",
     "//base",
-    "//components/web_package/signed_web_bundles/rust:signed_web_bundles_rust_bindings",
     "//crypto",
     "//mojo/public/cpp/bindings",
   ]
@@ -160,7 +158,6 @@
     "//base/test:test_support",
     "//components/cbor",
     "//components/web_package/rust:web_package_rust_unittests",
-    "//components/web_package/signed_web_bundles/rust:signed_web_bundles_rust_unittests",
     "//components/web_package/test_support",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/test_support:test_utils",
diff --git a/components/web_package/signed_web_bundles/ecdsa_p256_sha256_signature.cc b/components/web_package/signed_web_bundles/ecdsa_p256_sha256_signature.cc
index 2d820f0..b5a5ffb 100644
--- a/components/web_package/signed_web_bundles/ecdsa_p256_sha256_signature.cc
+++ b/components/web_package/signed_web_bundles/ecdsa_p256_sha256_signature.cc
@@ -9,7 +9,8 @@
 #include "base/strings/stringprintf.h"
 #include "base/types/expected.h"
 #include "components/web_package/signed_web_bundles/ecdsa_p256_public_key.h"
-#include "components/web_package/signed_web_bundles/rust/signed_web_bundles_rust.h"
+#include "crypto/keypair.h"
+#include "crypto/sign.h"
 
 namespace web_package {
 
@@ -50,8 +51,9 @@ EcdsaP256SHA256Signature::EcdsaP256SHA256Signature(std::vector<uint8_t> bytes)
 [[nodiscard]] bool EcdsaP256SHA256Signature::Verify(
     base::span<const uint8_t> message,
     const EcdsaP256PublicKey& public_key) const {
-  return signed_web_bundles::rust::verify_ecdsa_p256_signature(
-      public_key.bytes(), bytes(), message);
+  auto key = crypto::keypair::PublicKey::FromEcP256Point(public_key.bytes());
+  return crypto::sign::Verify(crypto::sign::ECDSA_SHA256, *key, message,
+                              bytes());
 }
 
 }  // namespace web_package
diff --git a/components/web_package/signed_web_bundles/ed25519_signature.cc b/components/web_package/signed_web_bundles/ed25519_signature.cc
index 1011178..62e24ae 100644
--- a/components/web_package/signed_web_bundles/ed25519_signature.cc
+++ b/components/web_package/signed_web_bundles/ed25519_signature.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 
 #include "base/strings/stringprintf.h"
-#include "components/web_package/signed_web_bundles/rust/signed_web_bundles_rust.h"
 #include "third_party/boringssl/src/include/openssl/curve25519.h"
 
 namespace web_package {
@@ -43,8 +42,11 @@ Ed25519Signature::Ed25519Signature(std::array<uint8_t, kLength>& bytes)
 [[nodiscard]] bool Ed25519Signature::Verify(
     base::span<const uint8_t> message,
     const Ed25519PublicKey& public_key) const {
-  return signed_web_bundles::rust::verify_ed25519_signature(public_key.bytes(),
-                                                            bytes(), message);
+  const std::array<uint8_t, ED25519_PUBLIC_KEY_LEN>& public_key_bytes =
+      public_key.bytes();
+  const std::array<uint8_t, ED25519_SIGNATURE_LEN>& signature_bytes = bytes();
+  return ED25519_verify(message.data(), message.size(), signature_bytes.data(),
+                        public_key_bytes.data());
 }
 
 }  // namespace web_package
diff --git a/components/web_package/signed_web_bundles/integrity_block_parser.cc b/components/web_package/signed_web_bundles/integrity_block_parser.cc
index c4717fc..437124a 100644
--- a/components/web_package/signed_web_bundles/integrity_block_parser.cc
+++ b/components/web_package/signed_web_bundles/integrity_block_parser.cc
@@ -4,16 +4,19 @@
 
 #include "components/web_package/signed_web_bundles/integrity_block_parser.h"
 
+#include <algorithm>
 #include <string>
-#include <string_view>
 #include <vector>
 
-#include "base/check.h"
-#include "base/containers/span.h"
+#include "base/containers/map_util.h"
 #include "base/functional/bind.h"
 #include "base/strings/stringprintf.h"
+#include "base/strings/to_string.h"
 #include "base/types/expected.h"
 #include "base/types/expected_macros.h"
+#include "components/cbor/reader.h"
+#include "components/cbor/writer.h"
+#include "components/web_package/mojom/web_bundle_parser.mojom-forward.h"
 #include "components/web_package/mojom/web_bundle_parser.mojom.h"
 #include "components/web_package/signed_web_bundles/constants.h"
 #include "components/web_package/signed_web_bundles/ecdsa_p256_public_key.h"
@@ -22,56 +24,11 @@
 #include "components/web_package/signed_web_bundles/ed25519_public_key.h"
 #include "components/web_package/signed_web_bundles/ed25519_signature.h"
 #include "components/web_package/signed_web_bundles/integrity_block_attributes.h"
-#include "components/web_package/signed_web_bundles/rust/signed_web_bundles_rust.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
 #include "components/web_package/signed_web_bundles/types.h"
 
 namespace web_package {
 
-namespace {
-
-using SignatureType = signed_web_bundles::rust::SignatureType::Tag;
-using signed_web_bundles::rust::parse_integrity_block;
-
-base::expected<mojom::BundleIntegrityBlockSignatureStackEntryPtr, std::string>
-CreateSignatureStackEntry(
-    const signed_web_bundles::rust::SignatureStackEntry& entry) {
-  auto parsed_sig = mojom::BundleIntegrityBlockSignatureStackEntry::New();
-
-  switch (entry.signature_type.tag) {
-    case SignatureType::Ed25519: {
-      ASSIGN_OR_RETURN(auto public_key,
-                       Ed25519PublicKey::Create(entry.public_key.to_span()));
-      ASSIGN_OR_RETURN(auto signature,
-                       Ed25519Signature::Create(entry.signature.to_span()));
-      parsed_sig->signature_info = mojom::SignatureInfo::NewEd25519(
-          mojom::SignatureInfoEd25519::New(public_key, signature));
-      break;
-    }
-    case SignatureType::EcdsaP256SHA256: {
-      ASSIGN_OR_RETURN(auto public_key,
-                       EcdsaP256PublicKey::Create(entry.public_key.to_span()));
-      ASSIGN_OR_RETURN(auto signature, EcdsaP256SHA256Signature::Create(
-                                           entry.signature.to_span()));
-      parsed_sig->signature_info = mojom::SignatureInfo::NewEcdsaP256Sha256(
-          mojom::SignatureInfoEcdsaP256SHA256::New(public_key, signature));
-      break;
-    }
-    case SignatureType::Unknown: {
-      parsed_sig->signature_info =
-          mojom::SignatureInfo::NewUnknown(mojom::SignatureInfoUnknown::New());
-      break;
-    }
-  }
-
-  parsed_sig->attributes_cbor =
-      BinaryData(entry.attributes_cbor.begin(), entry.attributes_cbor.end());
-
-  return parsed_sig;
-}
-
-}  // namespace
-
 IntegrityBlockParser::IntegrityBlockParser(
     mojom::BundleDataSource& data_source,
     WebBundleParser::ParseIntegrityBlockCallback callback)
@@ -103,37 +60,103 @@ void IntegrityBlockParser::OnIntegrityBlockRead(
     RunErrorCallback("Error reading the integrity block.");
     return;
   }
+  // This structure is built during parsing and returned by the final callback
+  mojom::BundleIntegrityBlockPtr integrity_block =
+      mojom::BundleIntegrityBlock::New();
+
+  size_t consumed_bytes = 0;
+  cbor::Reader::DecoderError error;
+  cbor::Reader::Config config;
+  config.num_bytes_consumed = &consumed_bytes;
+  config.error_code_out = &error;
+
+  // When config `bytes_consumed` are assigned the CBOR parser reads only to the
+  // end of a structure. It parses only Integrity Block even if Web Bundle part
+  // starts just after.
+  std::optional<cbor::Value> value = cbor::Reader::Read(*data, config);
+  if (!value) {
+    RunErrorCallback("Error parsing integrity block as CBOR: " +
+                     std::string(cbor::Reader::ErrorCodeToString(error)));
+    return;
+  }
+  integrity_block->size = consumed_bytes;
 
-  const auto parse_res = parse_integrity_block(*data);
-  if (!parse_res.has_value()) {
-    const auto& error = parse_res.error();
-    RunErrorCallback(std::string(error.message.as_str()),
-                     error.is_version_error
-                         ? mojom::BundleParseErrorType::kVersionError
-                         : mojom::BundleParseErrorType::kFormatError);
+  if (!value->is_array()) {
+    RunErrorCallback("Integrity block is not a CBOR array.");
     return;
   }
 
-  const auto& parsed_ib = *parse_res;
-  auto integrity_block = mojom::BundleIntegrityBlock::New();
-  integrity_block->size = parsed_ib.size;
+  const cbor::Value::ArrayValue& top_array = value->GetArray();
+  if (top_array.size() != kIntegrityBlockV2TopLevelArrayLength) {
+    RunErrorCallback(base::StringPrintf(
+        "Invalid integrity block array length: expected %u, got %zu.",
+        kIntegrityBlockV2TopLevelArrayLength, top_array.size()));
+    return;
+  }
 
-  const std::string_view web_bundle_id_str =
-      parsed_ib.web_bundle_id.to_string_view();
-  RETURN_IF_ERROR(
-      SignedWebBundleId::Create(web_bundle_id_str),
-      [&](std::string error) { RunErrorCallback(std::move(error)); });
+  // 1. Magic bytes
+  if (!top_array[0].is_bytestring() ||
+      !std::ranges::equal(top_array[0].GetBytestring(),
+                          kIntegrityBlockMagicBytes)) {
+    RunErrorCallback("Unexpected magic bytes.");
+    return;
+  }
 
-  integrity_block->attributes =
-      IntegrityBlockAttributes(std::string(web_bundle_id_str),
-                               BinaryData(parsed_ib.attributes_cbor.begin(),
-                                          parsed_ib.attributes_cbor.end()));
+  // 2. Version
+  if (!top_array[1].is_bytestring() ||
+      !std::ranges::equal(top_array[1].GetBytestring(),
+                          kIntegrityBlockV2VersionBytes)) {
+    RunErrorCallback("Unexpected version bytes.",
+                     mojom::BundleParseErrorType::kVersionError);
+    return;
+  }
 
-  for (const auto& entry : parsed_ib.signature_stack) {
+  // 3. Attributes
+  if (!top_array[2].is_map()) {
+    RunErrorCallback("Integrity block attributes must be a map.");
+    return;
+  }
+  const cbor::Value::MapValue& attributes_map = top_array[2].GetMap();
+  const cbor::Value* web_bundle_id =
+      base::FindOrNull(attributes_map, cbor::Value(kWebBundleIdAttributeName));
+  if (!web_bundle_id || !web_bundle_id->is_string()) {
+    RunErrorCallback(
+        "`webBundleId` integrity block attribute is missing or malformed.");
+    return;
+  }
+
+  // Check if web_bundle_id is correct
+  RETURN_IF_ERROR(SignedWebBundleId::Create(web_bundle_id->GetString()),
+                  [&](const std::string& error) { RunErrorCallback(error); });
+
+  BinaryData attributes_cbor = *cbor::Writer::Write(top_array[2]);
+  integrity_block->attributes = IntegrityBlockAttributes(
+      web_bundle_id->GetString(), std::move(attributes_cbor));
+
+  // 4. Signature Stack
+  if (!top_array[3].is_array()) {
+    RunErrorCallback("Signature stack must be an array.");
+    return;
+  }
+  const cbor::Value::ArrayValue& signatures = top_array[3].GetArray();
+  if (signatures.empty()) {
+    RunErrorCallback(
+        "The signature stack must contain at least one signature.");
+    return;
+  }
+
+  for (const auto& signature_info_raw : signatures) {
     ASSIGN_OR_RETURN(
-        auto parsed_sig, CreateSignatureStackEntry(entry),
-        [&](std::string error) { RunErrorCallback(std::move(error)); });
-    integrity_block->signature_stack.push_back(std::move(parsed_sig));
+        auto parsed_signature_info, ParseSignatureInfo(signature_info_raw),
+        [&](const std::string& error) { this->RunErrorCallback(error); });
+
+    if (integrity_block->signature_stack.empty() &&
+        parsed_signature_info->signature_info->is_unknown()) {
+      RunErrorCallback("Unknown cipher type of the first signature.");
+      return;
+    }
+    integrity_block->signature_stack.push_back(
+        std::move(parsed_signature_info));
   }
 
   std::move(complete_callback_)
@@ -141,13 +164,74 @@ void IntegrityBlockParser::OnIntegrityBlockRead(
                           std::move(integrity_block), nullptr));
 }
 
+base::expected<mojom::BundleIntegrityBlockSignatureStackEntryPtr, std::string>
+IntegrityBlockParser::ParseSignatureInfo(
+    const cbor::Value& signature_info_raw) {
+  if (!signature_info_raw.is_array() ||
+      signature_info_raw.GetArray().size() != 2) {
+    return base::unexpected(
+        "Each signature stack entry must contain exactly two elements.");
+  }
+
+  const cbor::Value::ArrayValue& signature_info_array =
+      signature_info_raw.GetArray();
+  if (!signature_info_array[0].is_map() ||
+      !signature_info_array[1].is_bytestring()) {
+    return base::unexpected("Malformed signature stack entry.");
+  }
+
+  mojom::BundleIntegrityBlockSignatureStackEntryPtr parsed_signature_info =
+      mojom::BundleIntegrityBlockSignatureStackEntry::New();
+  parsed_signature_info->attributes_cbor =
+      *cbor::Writer::Write(signature_info_array[0]);
+
+  const cbor::Value::MapValue& signature_attributes =
+      signature_info_array[0].GetMap();
+  const BinaryData& signature_bytes = signature_info_array[1].GetBytestring();
+
+  const cbor::Value* ed25519_key = base::FindOrNull(
+      signature_attributes, cbor::Value(kEd25519PublicKeyAttributeName));
+  const cbor::Value* ecdsa_key = base::FindOrNull(
+      signature_attributes, cbor::Value(kEcdsaP256PublicKeyAttributeName));
+
+  if (ed25519_key && ecdsa_key) {
+    return base::unexpected("Multiple key types for one signature.");
+  } else if (ed25519_key && !ed25519_key->is_bytestring()) {
+    return base::unexpected("Invalid ED25519 key.");
+  } else if (ecdsa_key && !ecdsa_key->is_bytestring()) {
+    return base::unexpected("Invalid ECDSA key.");
+
+  } else if (ed25519_key && ed25519_key->is_bytestring()) {
+    ASSIGN_OR_RETURN(auto public_key,
+                     Ed25519PublicKey::Create(ed25519_key->GetBytestring()));
+    ASSIGN_OR_RETURN(auto signature, Ed25519Signature::Create(signature_bytes));
+    parsed_signature_info->signature_info = mojom::SignatureInfo::NewEd25519(
+        mojom::SignatureInfoEd25519::New(public_key, signature));
+
+  } else if (ecdsa_key && ecdsa_key->is_bytestring()) {
+    ASSIGN_OR_RETURN(auto public_key,
+                     EcdsaP256PublicKey::Create(ecdsa_key->GetBytestring()));
+    ASSIGN_OR_RETURN(auto signature,
+                     EcdsaP256SHA256Signature::Create(signature_bytes));
+    parsed_signature_info->signature_info =
+        mojom::SignatureInfo::NewEcdsaP256Sha256(
+            mojom::SignatureInfoEcdsaP256SHA256::New(public_key, signature));
+
+  } else {
+    parsed_signature_info->signature_info =
+        mojom::SignatureInfo::NewUnknown(mojom::SignatureInfoUnknown::New());
+  }
+
+  return parsed_signature_info;
+}
+
 void IntegrityBlockParser::RunErrorCallback(
-    std::string message,
+    const std::string& message,
     mojom::BundleParseErrorType error_type) {
   std::move(complete_callback_)
-      .Run(base::BindOnce(std::move(result_callback_), nullptr,
-                          mojom::BundleIntegrityBlockParseError::New(
-                              error_type, std::move(message))));
+      .Run(base::BindOnce(
+          std::move(result_callback_), nullptr,
+          mojom::BundleIntegrityBlockParseError::New(error_type, message)));
 }
 
 }  // namespace web_package
diff --git a/components/web_package/signed_web_bundles/integrity_block_parser.h b/components/web_package/signed_web_bundles/integrity_block_parser.h
index 58263b0..b8140f2 100644
--- a/components/web_package/signed_web_bundles/integrity_block_parser.h
+++ b/components/web_package/signed_web_bundles/integrity_block_parser.h
@@ -5,13 +5,8 @@
 #ifndef COMPONENTS_WEB_PACKAGE_SIGNED_WEB_BUNDLES_INTEGRITY_BLOCK_PARSER_H_
 #define COMPONENTS_WEB_PACKAGE_SIGNED_WEB_BUNDLES_INTEGRITY_BLOCK_PARSER_H_
 
-#include <optional>
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/memory/raw_ref.h"
-#include "base/memory/weak_ptr.h"
 #include "components/web_package/mojom/web_bundle_parser.mojom-forward.h"
+#include "components/web_package/signed_web_bundles/integrity_block_attributes.h"
 #include "components/web_package/signed_web_bundles/types.h"
 #include "components/web_package/web_bundle_parser.h"
 
@@ -20,7 +15,7 @@ namespace web_package {
 class IntegrityBlockParser : public WebBundleParser::WebBundleSectionParser {
  public:
   explicit IntegrityBlockParser(
-      mojom::BundleDataSource& data_source LIFETIME_BOUND,
+      mojom::BundleDataSource& data_source,
       WebBundleParser::ParseIntegrityBlockCallback callback);
 
   IntegrityBlockParser(const IntegrityBlockParser&) = delete;
@@ -35,7 +30,10 @@ class IntegrityBlockParser : public WebBundleParser::WebBundleSectionParser {
  private:
   void OnIntegrityBlockRead(const std::optional<BinaryData>& data);
 
-  void RunErrorCallback(std::string message,
+  base::expected<mojom::BundleIntegrityBlockSignatureStackEntryPtr, std::string>
+  ParseSignatureInfo(const cbor::Value& attributes_map);
+
+  void RunErrorCallback(const std::string& message,
                         mojom::BundleParseErrorType error_type =
                             mojom::BundleParseErrorType::kFormatError);
 
diff --git a/components/web_package/signed_web_bundles/rust/BUILD.gn b/components/web_package/signed_web_bundles/rust/BUILD.gn
deleted file mode 100644
index 8e1bf00..0000000
--- a/components/web_package/signed_web_bundles/rust/BUILD.gn
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2026 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/rust/rust_static_library.gni")
-
-rust_static_library("signed_web_bundles_rust") {
-  visibility = [ "//components/web_package/*" ]
-  crate_name = "signed_web_bundles_rust"
-  crate_root = "lib.rs"
-  sources = [
-    "constants.rs",
-    "integrity_block.rs",
-    "signature_verifier.rs",
-    "types.rs",
-    crate_root,
-  ]
-
-  cpp_api_from_rust = {
-    target_name = "signed_web_bundles_rust_bindings"
-    cpp_namespace = "web_package::signed_web_bundles::rust"
-    h_out = "${target_gen_dir}/signed_web_bundles_rust.h"
-  }
-
-  deps = [
-    "//components/cbor/rust:cbor",
-    "//third_party/boringssl:bssl_crypto",
-  ]
-}
-
-rust_static_library("signed_web_bundles_rust_unittests") {
-  testonly = true
-  is_gtest_unittests = true
-  crate_root = "signed_web_bundles_rust_unittests.rs"
-  sources = [
-    "integrity_block_unittest.rs",
-    crate_root,
-  ]
-  deps = [
-    ":signed_web_bundles_rust",
-    "//components/cbor/rust:cbor",
-    "//testing/rust_gtest_interop",
-  ]
-}
diff --git a/components/web_package/signed_web_bundles/rust/constants.rs b/components/web_package/signed_web_bundles/rust/constants.rs
deleted file mode 100644
index cc29376..0000000
--- a/components/web_package/signed_web_bundles/rust/constants.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2026 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-pub const MAGIC_BYTES: &[u8] = b"\xF0\x9F\x96\x8B\xF0\x9F\x93\xA6";
-pub const V2_VERSION_BYTES: &[u8] = b"2b\0\0";
-pub const WEB_BUNDLE_ID_ATTRIBUTE_NAME: &str = "webBundleId";
-pub const ED25519_PUBLIC_KEY_ATTRIBUTE_NAME: &str = "ed25519PublicKey";
-pub const ECDSA_P256_PUBLIC_KEY_ATTRIBUTE_NAME: &str = "ecdsaP256SHA256PublicKey";
-pub const TOP_LEVEL_ARRAY_LENGTH: usize = 4;
-
-/// Length in bytes of a compressed ECDSA P-256 public key (SEC 1 / X9.62
-/// format: 0x02 or 0x03 tag prefix followed by the 32-byte X coordinate).
-pub const ECDSA_P256_PUBLIC_KEY_LEN: usize = 33;
-
-/// Minimum and maximum valid byte lengths of an ASN.1 DER-encoded ECDSA P-256
-/// signature sequence containing integers (r, s).
-pub const ECDSA_P256_SIGNATURE_MIN_LEN: usize = 64;
-pub const ECDSA_P256_SIGNATURE_MAX_LEN: usize = 72;
diff --git a/components/web_package/signed_web_bundles/rust/integrity_block.rs b/components/web_package/signed_web_bundles/rust/integrity_block.rs
deleted file mode 100644
index 77ce037..0000000
--- a/components/web_package/signed_web_bundles/rust/integrity_block.rs
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright 2026 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use alloc::format;
-use alloc::vec::Vec;
-
-use crate::constants::{
-    ECDSA_P256_PUBLIC_KEY_ATTRIBUTE_NAME, ECDSA_P256_PUBLIC_KEY_LEN, ECDSA_P256_SIGNATURE_MAX_LEN,
-    ECDSA_P256_SIGNATURE_MIN_LEN, ED25519_PUBLIC_KEY_ATTRIBUTE_NAME, MAGIC_BYTES,
-    TOP_LEVEL_ARRAY_LENGTH, V2_VERSION_BYTES, WEB_BUNDLE_ID_ATTRIBUTE_NAME,
-};
-use crate::types::{IntegrityBlock, ParseError, SignatureStackEntry, SignatureType};
-
-fn validate_keys_and_signature(
-    signature_type: SignatureType,
-    public_key: &[u8],
-    signature: &[u8],
-) -> Result<(), ParseError> {
-    match signature_type {
-        SignatureType::Ed25519 => {
-            if public_key.len() != bssl_crypto::ed25519::PUBLIC_KEY_LEN {
-                return Err(ParseError::format(format!(
-                    "The Ed25519 public key does not have the correct length. Expected {} bytes, but received {} bytes.",
-                    bssl_crypto::ed25519::PUBLIC_KEY_LEN,
-                    public_key.len()
-                )));
-            }
-            if signature.len() != bssl_crypto::ed25519::SIGNATURE_LEN {
-                return Err(ParseError::format(format!(
-                    "The signature has the wrong length. Expected {}, but got {} bytes.",
-                    bssl_crypto::ed25519::SIGNATURE_LEN,
-                    signature.len()
-                )));
-            }
-        }
-        SignatureType::EcdsaP256SHA256 => {
-            if public_key.len() != ECDSA_P256_PUBLIC_KEY_LEN {
-                return Err(ParseError::format(format!(
-                    "The ECDSA P-256 public key does not have the correct length. Expected {} bytes, but received {} bytes.",
-                    ECDSA_P256_PUBLIC_KEY_LEN,
-                    public_key.len()
-                )));
-            }
-            if bssl_crypto::ecdsa::PublicKey::<bssl_crypto::ec::P256>::from_x962_compressed(
-                public_key,
-            )
-            .is_none()
-            {
-                return Err(ParseError::format(
-                    "Unable to parse a valid ECDSA P-256 key from the given bytes.",
-                ));
-            }
-            if signature.len() < ECDSA_P256_SIGNATURE_MIN_LEN
-                || signature.len() > ECDSA_P256_SIGNATURE_MAX_LEN
-            {
-                return Err(ParseError::format(format!(
-                    "The ECDSA P-256 SHA-256 signature does not have the correct length. Expected from {} to {} bytes, but received {} bytes.",
-                    ECDSA_P256_SIGNATURE_MIN_LEN,
-                    ECDSA_P256_SIGNATURE_MAX_LEN,
-                    signature.len()
-                )));
-            }
-        }
-        SignatureType::Unknown => {}
-    }
-    Ok(())
-}
-
-fn parse_signature_info<'a>(
-    entry: &cbor::Value<'a>,
-) -> Result<SignatureStackEntry<'a>, ParseError> {
-    let cbor::Value::Array(sig_array) = entry else {
-        return Err(ParseError::format("Each signature stack entry must be a CBOR array."));
-    };
-
-    let [cbor::Value::Map(attributes_map), cbor::Value::Bytestring(signature_bytes)] =
-        sig_array.as_slice()
-    else {
-        if sig_array.len() != 2 {
-            return Err(ParseError::format(
-                "Each signature stack entry must contain exactly two elements.",
-            ));
-        }
-        return Err(ParseError::format("Malformed signature stack entry."));
-    };
-
-    let ed25519_key = attributes_map.get(&cbor::MapKey::String(ED25519_PUBLIC_KEY_ATTRIBUTE_NAME));
-    let ecdsa_key = attributes_map.get(&cbor::MapKey::String(ECDSA_P256_PUBLIC_KEY_ATTRIBUTE_NAME));
-
-    let (signature_type, public_key) = match (ed25519_key, ecdsa_key) {
-        (Some(_), Some(_)) => {
-            return Err(ParseError::format("Multiple key types for one signature."));
-        }
-        (Some(cbor::Value::Bytestring(pk)), None) => (SignatureType::Ed25519, *pk),
-        (Some(_), None) => return Err(ParseError::format("Invalid ED25519 key.")),
-        (None, Some(cbor::Value::Bytestring(pk))) => (SignatureType::EcdsaP256SHA256, *pk),
-        (None, Some(_)) => return Err(ParseError::format("Invalid ECDSA key.")),
-        (None, None) => (SignatureType::Unknown, &[][..]),
-    };
-
-    validate_keys_and_signature(signature_type, public_key, signature_bytes)?;
-
-    let attributes_cbor = cbor::write(&sig_array[0]);
-
-    Ok(SignatureStackEntry {
-        attributes_cbor,
-        signature_type,
-        public_key,
-        signature: signature_bytes,
-    })
-}
-
-pub fn parse_integrity_block<'a>(input: &'a [u8]) -> Result<IntegrityBlock<'a>, ParseError> {
-    let parse_result = cbor::parse_with_config(input, cbor::Config::default())
-        .map_err(|e| ParseError::format(format!("Error parsing integrity block as CBOR: {}", e)))?;
-
-    let cbor::Value::Array(top_array) = &parse_result.value else {
-        return Err(ParseError::format("Integrity block is not a CBOR array."));
-    };
-
-    if top_array.len() != TOP_LEVEL_ARRAY_LENGTH {
-        return Err(ParseError::format(format!(
-            "Invalid integrity block array length: expected {}, got {}.",
-            TOP_LEVEL_ARRAY_LENGTH,
-            top_array.len()
-        )));
-    }
-
-    // 1. Magic bytes
-    let cbor::Value::Bytestring(MAGIC_BYTES) = &top_array[0] else {
-        return Err(ParseError::format("Unexpected magic bytes."));
-    };
-
-    // 2. Version bytes
-    let cbor::Value::Bytestring(V2_VERSION_BYTES) = &top_array[1] else {
-        return Err(ParseError::version("Unexpected version bytes."));
-    };
-
-    // 3. Attributes map
-    let cbor::Value::Map(attributes_map) = &top_array[2] else {
-        return Err(ParseError::format("Integrity block attributes must be a map."));
-    };
-
-    let Some(cbor::Value::String(web_bundle_id)) =
-        attributes_map.get(&cbor::MapKey::String(WEB_BUNDLE_ID_ATTRIBUTE_NAME))
-    else {
-        return Err(ParseError::format(
-            "`webBundleId` integrity block attribute is missing or malformed.",
-        ));
-    };
-
-    // 4. Signature Stack
-    let cbor::Value::Array(signatures) = &top_array[3] else {
-        return Err(ParseError::format("Signature stack must be an array."));
-    };
-
-    if signatures.is_empty() {
-        return Err(ParseError::format("The signature stack must contain at least one signature."));
-    }
-
-    let mut signature_stack = Vec::with_capacity(signatures.len());
-    for (i, sig_entry) in signatures.iter().enumerate() {
-        let parsed = parse_signature_info(sig_entry)?;
-        if i == 0 && parsed.signature_type == SignatureType::Unknown {
-            return Err(ParseError::format("Unknown cipher type of the first signature."));
-        }
-        signature_stack.push(parsed);
-    }
-
-    let attributes_cbor = cbor::write(&top_array[2]);
-
-    Ok(IntegrityBlock {
-        size: parse_result.bytes_consumed,
-        web_bundle_id,
-        attributes_cbor,
-        signature_stack,
-    })
-}
diff --git a/components/web_package/signed_web_bundles/rust/integrity_block_unittest.rs b/components/web_package/signed_web_bundles/rust/integrity_block_unittest.rs
deleted file mode 100644
index 108ecb9..0000000
--- a/components/web_package/signed_web_bundles/rust/integrity_block_unittest.rs
+++ /dev/null
@@ -1,474 +0,0 @@
-// Copyright 2026 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use cbor::{Map, MapEntry, MapKey, Value};
-use rust_gtest_interop::prelude::*;
-use signed_web_bundles_rust::*;
-
-const VALID_ECDSA_P256_PK: &[u8; 33] =
-    b"\x02\x6b\x17\xd1\xf2\xe1\x2c\x42\x47\xf8\xbc\xe6\xe5\x63\xa4\x40\xf2\x77\x03\x7d\x81\x2d\xeb\x33\xa0\xf4\xa1\x39\x45\xd8\x98\xc2\x96";
-
-fn make_top_attributes(bundle_id: &str) -> Value<'_> {
-    Value::Map(Map::from(vec![MapEntry::from((
-        MapKey::String("webBundleId"),
-        Value::String(bundle_id),
-    ))]))
-}
-
-fn make_ed25519_sig_entry<'a>(pk: &'a [u8], sig: &'a [u8]) -> Value<'a> {
-    Value::Array(vec![
-        Value::Map(Map::from(vec![MapEntry::from((
-            MapKey::String("ed25519PublicKey"),
-            Value::Bytestring(pk),
-        ))])),
-        Value::Bytestring(sig),
-    ])
-}
-
-fn make_valid_ib_cbor() -> Vec<u8> {
-    let top_array = Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![make_ed25519_sig_entry(&[0x42; 32], &[0x24; 64])]),
-    ]);
-    cbor::write(&top_array)
-}
-
-#[gtest(IntegrityBlockRustTest, TestInvalidCbor)]
-fn test_invalid_cbor() {
-    let result = parse_integrity_block(&[0xff]);
-    assert!(result.is_err());
-    let err = result.unwrap_err();
-    assert!(!err.is_version_error);
-    assert!(err.message.as_str().starts_with("Error parsing integrity block as CBOR:"));
-}
-
-#[gtest(IntegrityBlockRustTest, TestNotACborArray)]
-fn test_not_a_cbor_array() {
-    let data = cbor::write(&Value::Int(42));
-    let err = parse_integrity_block(&data).unwrap_err();
-    assert_eq!(err.message.as_str(), "Integrity block is not a CBOR array.");
-    assert!(!err.is_version_error);
-}
-
-#[gtest(IntegrityBlockRustTest, TestInvalidArrayLength)]
-fn test_invalid_array_length() {
-    let data = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-    ]));
-    let err = parse_integrity_block(&data).unwrap_err();
-    assert_eq!(err.message.as_str(), "Invalid integrity block array length: expected 4, got 3.");
-}
-
-#[gtest(IntegrityBlockRustTest, TestUnexpectedMagicBytes)]
-fn test_unexpected_magic_bytes() {
-    let data = cbor::write(&Value::Array(vec![
-        Value::Bytestring(b"badmagic"),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![make_ed25519_sig_entry(&[0x42; 32], &[0x24; 64])]),
-    ]));
-    let err = parse_integrity_block(&data).unwrap_err();
-    assert_eq!(err.message.as_str(), "Unexpected magic bytes.");
-    assert!(!err.is_version_error);
-}
-
-#[gtest(IntegrityBlockRustTest, TestUnexpectedVersionBytes)]
-fn test_unexpected_version_bytes() {
-    let data = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(b"3b\0\0"),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![make_ed25519_sig_entry(&[0x42; 32], &[0x24; 64])]),
-    ]));
-    let err = parse_integrity_block(&data).unwrap_err();
-    assert_eq!(err.message.as_str(), "Unexpected version bytes.");
-    assert!(err.is_version_error);
-}
-
-#[gtest(IntegrityBlockRustTest, TestAttributesNotAMap)]
-fn test_attributes_not_a_map() {
-    let data = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        Value::Array(vec![]),
-        Value::Array(vec![make_ed25519_sig_entry(&[0x42; 32], &[0x24; 64])]),
-    ]));
-    let err = parse_integrity_block(&data).unwrap_err();
-    assert_eq!(err.message.as_str(), "Integrity block attributes must be a map.");
-}
-
-#[gtest(IntegrityBlockRustTest, TestMissingOrMalformedWebBundleId)]
-fn test_missing_or_malformed_web_bundle_id() {
-    // Missing webBundleId
-    let data_missing = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        Value::Map(Map::new()),
-        Value::Array(vec![make_ed25519_sig_entry(&[0x42; 32], &[0x24; 64])]),
-    ]));
-    let err = parse_integrity_block(&data_missing).unwrap_err();
-    assert_eq!(
-        err.message.as_str(),
-        "`webBundleId` integrity block attribute is missing or malformed."
-    );
-
-    // Malformed webBundleId (int instead of string)
-    let data_malformed = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        Value::Map(Map::from(vec![MapEntry::from((
-            MapKey::String("webBundleId"),
-            Value::Int(123),
-        ))])),
-        Value::Array(vec![make_ed25519_sig_entry(&[0x42; 32], &[0x24; 64])]),
-    ]));
-    let err2 = parse_integrity_block(&data_malformed).unwrap_err();
-    assert_eq!(
-        err2.message.as_str(),
-        "`webBundleId` integrity block attribute is missing or malformed."
-    );
-}
-
-#[gtest(IntegrityBlockRustTest, TestSignatureStackNotAnArray)]
-fn test_signature_stack_not_an_array() {
-    let data = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Int(123),
-    ]));
-    let err = parse_integrity_block(&data).unwrap_err();
-    assert_eq!(err.message.as_str(), "Signature stack must be an array.");
-}
-
-#[gtest(IntegrityBlockRustTest, TestSignatureStackEmpty)]
-fn test_signature_stack_empty() {
-    let data = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![]),
-    ]));
-    let err = parse_integrity_block(&data).unwrap_err();
-    assert_eq!(err.message.as_str(), "The signature stack must contain at least one signature.");
-}
-
-#[gtest(IntegrityBlockRustTest, TestSignatureStackEntryNotAnArray)]
-fn test_signature_stack_entry_not_an_array() {
-    let data = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![Value::Int(123)]),
-    ]));
-    let err = parse_integrity_block(&data).unwrap_err();
-    assert_eq!(err.message.as_str(), "Each signature stack entry must be a CBOR array.");
-
-    let data_map = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![Value::Map(Map::new())]),
-    ]));
-    let err_map = parse_integrity_block(&data_map).unwrap_err();
-    assert_eq!(err_map.message.as_str(), "Each signature stack entry must be a CBOR array.");
-}
-
-#[gtest(IntegrityBlockRustTest, TestSignatureStackEntryWrongLength)]
-fn test_signature_stack_entry_wrong_length() {
-    // Entry array with 1 item
-    let data_1 = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![Value::Array(vec![Value::Map(Map::new())])]),
-    ]));
-    let err_1 = parse_integrity_block(&data_1).unwrap_err();
-    assert_eq!(
-        err_1.message.as_str(),
-        "Each signature stack entry must contain exactly two elements."
-    );
-
-    // Entry array with 3 items
-    let data_3 = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![Value::Array(vec![
-            Value::Map(Map::new()),
-            Value::Bytestring(&[0x24; 64]),
-            Value::Int(3),
-        ])]),
-    ]));
-    let err_3 = parse_integrity_block(&data_3).unwrap_err();
-    assert_eq!(
-        err_3.message.as_str(),
-        "Each signature stack entry must contain exactly two elements."
-    );
-}
-
-#[gtest(IntegrityBlockRustTest, TestSignatureStackEntryMalformedTypes)]
-fn test_signature_stack_entry_malformed_types() {
-    let data = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![Value::Array(vec![
-            Value::Bytestring(b"not-a-map"),
-            Value::Bytestring(&[0x24; 64]),
-        ])]),
-    ]));
-    let err = parse_integrity_block(&data).unwrap_err();
-    assert_eq!(err.message.as_str(), "Malformed signature stack entry.");
-}
-
-#[gtest(IntegrityBlockRustTest, TestMultipleKeyTypes)]
-fn test_multiple_key_types() {
-    let data = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![Value::Array(vec![
-            Value::Map(Map::from(vec![
-                MapEntry::from((
-                    MapKey::String("ecdsaP256SHA256PublicKey"),
-                    Value::Bytestring(VALID_ECDSA_P256_PK),
-                )),
-                MapEntry::from((
-                    MapKey::String("ed25519PublicKey"),
-                    Value::Bytestring(&[0x42; 32]),
-                )),
-            ])),
-            Value::Bytestring(&[0x24; 64]),
-        ])]),
-    ]));
-    let err = parse_integrity_block(&data).unwrap_err();
-    assert_eq!(err.message.as_str(), "Multiple key types for one signature.");
-}
-
-#[gtest(IntegrityBlockRustTest, TestInvalidKeyAttributeTypes)]
-fn test_invalid_key_attribute_types() {
-    // ed25519PublicKey is integer instead of bytestring
-    let data_ed = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![Value::Array(vec![
-            Value::Map(Map::from(vec![MapEntry::from((
-                MapKey::String("ed25519PublicKey"),
-                Value::Int(123),
-            ))])),
-            Value::Bytestring(&[0x24; 64]),
-        ])]),
-    ]));
-    let err_ed = parse_integrity_block(&data_ed).unwrap_err();
-    assert_eq!(err_ed.message.as_str(), "Invalid ED25519 key.");
-
-    // ecdsaP256SHA256PublicKey is string instead of bytestring
-    let data_ec = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![Value::Array(vec![
-            Value::Map(Map::from(vec![MapEntry::from((
-                MapKey::String("ecdsaP256SHA256PublicKey"),
-                Value::String("not-bytes"),
-            ))])),
-            Value::Bytestring(&[0x24; 64]),
-        ])]),
-    ]));
-    let err_ec = parse_integrity_block(&data_ec).unwrap_err();
-    assert_eq!(err_ec.message.as_str(), "Invalid ECDSA key.");
-}
-
-#[gtest(IntegrityBlockRustTest, TestFirstSignatureUnknown)]
-fn test_first_signature_unknown() {
-    let data = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![Value::Array(vec![
-            Value::Map(Map::from(vec![MapEntry::from((
-                MapKey::String("otherCipherPublicKey"),
-                Value::Bytestring(&[0x42; 32]),
-            ))])),
-            Value::Bytestring(&[0x24; 64]),
-        ])]),
-    ]));
-    let err = parse_integrity_block(&data).unwrap_err();
-    assert_eq!(err.message.as_str(), "Unknown cipher type of the first signature.");
-}
-
-#[gtest(IntegrityBlockRustTest, TestEd25519KeyAndSignatureLengthValidation)]
-fn test_ed25519_key_and_signature_length_validation() {
-    // Wrong public key length (31 instead of 32)
-    let data_pk = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![make_ed25519_sig_entry(&[0x42; 31], &[0x24; 64])]),
-    ]));
-    let err_pk = parse_integrity_block(&data_pk).unwrap_err();
-    assert_eq!(
-        err_pk.message.as_str(),
-        "The Ed25519 public key does not have the correct length. Expected 32 bytes, but received 31 bytes."
-    );
-
-    // Wrong signature length (65 instead of 64)
-    let data_sig = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![make_ed25519_sig_entry(&[0x42; 32], &[0x24; 65])]),
-    ]));
-    let err_sig = parse_integrity_block(&data_sig).unwrap_err();
-    assert_eq!(
-        err_sig.message.as_str(),
-        "The signature has the wrong length. Expected 64, but got 65 bytes."
-    );
-}
-
-#[gtest(IntegrityBlockRustTest, TestEcdsaKeyAndSignatureValidation)]
-fn test_ecdsa_key_and_signature_validation() {
-    // Wrong public key length (32 instead of 33)
-    let data_pk_len = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![Value::Array(vec![
-            Value::Map(Map::from(vec![MapEntry::from((
-                MapKey::String("ecdsaP256SHA256PublicKey"),
-                Value::Bytestring(&VALID_ECDSA_P256_PK[..32]),
-            ))])),
-            Value::Bytestring(&[0x24; 64]),
-        ])]),
-    ]));
-    let err_pk_len = parse_integrity_block(&data_pk_len).unwrap_err();
-    assert_eq!(
-        err_pk_len.message.as_str(),
-        "The ECDSA P-256 public key does not have the correct length. Expected 33 bytes, but received 32 bytes."
-    );
-
-    // 33-byte public key that is not a valid curve point (invalid format prefix)
-    let invalid_curve_pk = vec![0x00; 33];
-    let data_pk_invalid = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![Value::Array(vec![
-            Value::Map(Map::from(vec![MapEntry::from((
-                MapKey::String("ecdsaP256SHA256PublicKey"),
-                Value::Bytestring(&invalid_curve_pk),
-            ))])),
-            Value::Bytestring(&[0x24; 64]),
-        ])]),
-    ]));
-    let err_pk_invalid = parse_integrity_block(&data_pk_invalid).unwrap_err();
-    assert_eq!(
-        err_pk_invalid.message.as_str(),
-        "Unable to parse a valid ECDSA P-256 key from the given bytes."
-    );
-
-    // Signature length too short (63 bytes)
-    let data_sig_short = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![Value::Array(vec![
-            Value::Map(Map::from(vec![MapEntry::from((
-                MapKey::String("ecdsaP256SHA256PublicKey"),
-                Value::Bytestring(VALID_ECDSA_P256_PK),
-            ))])),
-            Value::Bytestring(&[0x24; 63]),
-        ])]),
-    ]));
-    let err_sig_short = parse_integrity_block(&data_sig_short).unwrap_err();
-    assert_eq!(
-        err_sig_short.message.as_str(),
-        "The ECDSA P-256 SHA-256 signature does not have the correct length. Expected from 64 to 72 bytes, but received 63 bytes."
-    );
-
-    // Signature length too long (73 bytes)
-    let data_sig_long = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id"),
-        Value::Array(vec![Value::Array(vec![
-            Value::Map(Map::from(vec![MapEntry::from((
-                MapKey::String("ecdsaP256SHA256PublicKey"),
-                Value::Bytestring(VALID_ECDSA_P256_PK),
-            ))])),
-            Value::Bytestring(&[0x24; 73]),
-        ])]),
-    ]));
-    let err_sig_long = parse_integrity_block(&data_sig_long).unwrap_err();
-    assert_eq!(
-        err_sig_long.message.as_str(),
-        "The ECDSA P-256 SHA-256 signature does not have the correct length. Expected from 64 to 72 bytes, but received 73 bytes."
-    );
-}
-
-#[gtest(IntegrityBlockRustTest, TestValidEd25519IntegrityBlock)]
-fn test_valid_ed25519_integrity_block() {
-    let data = make_valid_ib_cbor();
-    let ib = parse_integrity_block(&data).expect("valid parse");
-    assert_eq!(ib.size, data.len());
-    assert_eq!(ib.web_bundle_id, "test-bundle-id");
-    assert_eq!(ib.signature_stack.len(), 1);
-    assert_eq!(ib.signature_stack[0].signature_type, SignatureType::Ed25519);
-    assert_eq!(ib.signature_stack[0].public_key, &[0x42; 32]);
-    assert_eq!(ib.signature_stack[0].signature, &[0x24; 64]);
-}
-
-#[gtest(IntegrityBlockRustTest, TestValidEcdsaIntegrityBlock)]
-fn test_valid_ecdsa_integrity_block() {
-    let data = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("test-bundle-id-ecdsa"),
-        Value::Array(vec![Value::Array(vec![
-            Value::Map(Map::from(vec![MapEntry::from((
-                MapKey::String("ecdsaP256SHA256PublicKey"),
-                Value::Bytestring(VALID_ECDSA_P256_PK),
-            ))])),
-            Value::Bytestring(&[0x24; 70]),
-        ])]),
-    ]));
-    let ib = parse_integrity_block(&data).expect("valid parse");
-    assert_eq!(ib.size, data.len());
-    assert_eq!(ib.web_bundle_id, "test-bundle-id-ecdsa");
-    assert_eq!(ib.signature_stack.len(), 1);
-    assert_eq!(ib.signature_stack[0].signature_type, SignatureType::EcdsaP256SHA256);
-    assert_eq!(ib.signature_stack[0].public_key, VALID_ECDSA_P256_PK.as_slice());
-    assert_eq!(ib.signature_stack[0].signature, &[0x24; 70]);
-}
-
-#[gtest(IntegrityBlockRustTest, TestValidMultiSignatureWithUnknownTrailing)]
-fn test_valid_multi_signature_with_unknown_trailing() {
-    let data = cbor::write(&Value::Array(vec![
-        Value::Bytestring(MAGIC_BYTES),
-        Value::Bytestring(V2_VERSION_BYTES),
-        make_top_attributes("multi-sig-bundle"),
-        Value::Array(vec![
-            make_ed25519_sig_entry(&[0x42; 32], &[0x24; 64]),
-            Value::Array(vec![
-                Value::Map(Map::from(vec![MapEntry::from((
-                    MapKey::String("unknownFutureCipherKey"),
-                    Value::Bytestring(&[0x99; 32]),
-                ))])),
-                Value::Bytestring(&[0x88; 64]),
-            ]),
-        ]),
-    ]));
-    let ib = parse_integrity_block(&data).expect("valid parse");
-    assert_eq!(ib.signature_stack.len(), 2);
-    assert_eq!(ib.signature_stack[0].signature_type, SignatureType::Ed25519);
-    assert_eq!(ib.signature_stack[1].signature_type, SignatureType::Unknown);
-    assert_eq!(ib.signature_stack[1].public_key, &[]);
-    assert_eq!(ib.signature_stack[1].signature, &[0x88; 64]);
-}
diff --git a/components/web_package/signed_web_bundles/rust/lib.rs b/components/web_package/signed_web_bundles/rust/lib.rs
deleted file mode 100644
index 7ff9adc..0000000
--- a/components/web_package/signed_web_bundles/rust/lib.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2026 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#![no_std]
-#![forbid(unsafe_code)]
-
-extern crate alloc;
-
-mod constants;
-mod integrity_block;
-mod signature_verifier;
-mod types;
-
-pub use constants::{
-    ECDSA_P256_PUBLIC_KEY_ATTRIBUTE_NAME, ECDSA_P256_PUBLIC_KEY_LEN, ECDSA_P256_SIGNATURE_MAX_LEN,
-    ECDSA_P256_SIGNATURE_MIN_LEN, ED25519_PUBLIC_KEY_ATTRIBUTE_NAME, MAGIC_BYTES,
-    TOP_LEVEL_ARRAY_LENGTH, V2_VERSION_BYTES, WEB_BUNDLE_ID_ATTRIBUTE_NAME,
-};
-pub use integrity_block::parse_integrity_block;
-pub use signature_verifier::{
-    create_empty_integrity_block_cbor, create_signature_payload, verify_ecdsa_p256_signature,
-    verify_ed25519_signature, verify_signature, Sha512Hasher,
-};
-pub use types::{IntegrityBlock, ParseError, SignatureStackEntry, SignatureType};
diff --git a/components/web_package/signed_web_bundles/rust/signature_verifier.rs b/components/web_package/signed_web_bundles/rust/signature_verifier.rs
deleted file mode 100644
index db885ba..0000000
--- a/components/web_package/signed_web_bundles/rust/signature_verifier.rs
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2026 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use alloc::vec::Vec;
-
-use crate::constants::{MAGIC_BYTES, V2_VERSION_BYTES};
-use crate::types::SignatureType;
-
-/// Constructs the CBOR representation of an integrity block with an empty
-/// signature array by parsing the pre-encoded attributes and serializing
-/// the top-level CBOR structure using the memory-safe CBOR writer.
-pub fn create_empty_integrity_block_cbor(attributes_cbor: &[u8]) -> Vec<u8> {
-    let attributes_value = match cbor::parse_with_config(attributes_cbor, cbor::Config::default()) {
-        Ok(parsed) => parsed.value,
-        Err(_) => cbor::Value::Map(Default::default()),
-    };
-
-    let top_array = cbor::Value::Array(alloc::vec![
-        cbor::Value::Bytestring(MAGIC_BYTES),
-        cbor::Value::Bytestring(V2_VERSION_BYTES),
-        attributes_value,
-        cbor::Value::Array(Vec::new()),
-    ]);
-
-    cbor::write(&top_array)
-}
-
-fn append_payload_item(payload: &mut Vec<u8>, item: &[u8]) {
-    payload.extend_from_slice(&(item.len() as u64).to_be_bytes());
-    payload.extend_from_slice(item);
-}
-
-/// Constructs the signature payload by concatenating 8-byte big-endian
-/// length-prefixed chunks: unsigned_web_bundle_hash, integrity_block_cbor, and
-/// attributes_cbor.
-pub fn create_signature_payload(
-    unsigned_web_bundle_hash: &[u8],
-    integrity_block_cbor: &[u8],
-    attributes_cbor: &[u8],
-) -> Vec<u8> {
-    let mut payload = Vec::with_capacity(
-        8 + unsigned_web_bundle_hash.len()
-            + 8
-            + integrity_block_cbor.len()
-            + 8
-            + attributes_cbor.len(),
-    );
-    append_payload_item(&mut payload, unsigned_web_bundle_hash);
-    append_payload_item(&mut payload, integrity_block_cbor);
-    append_payload_item(&mut payload, attributes_cbor);
-    payload
-}
-
-/// Verifies an Ed25519 signature over `message` using BoringSSL.
-#[must_use]
-pub fn verify_ed25519_signature(public_key: &[u8], signature: &[u8], message: &[u8]) -> bool {
-    let Ok(pk_bytes) = public_key.try_into() else {
-        return false;
-    };
-    let Ok(sig_bytes) = signature.try_into() else {
-        return false;
-    };
-    let pk = bssl_crypto::ed25519::PublicKey::from_bytes(pk_bytes);
-    pk.verify(message, sig_bytes).is_ok()
-}
-
-/// Verifies an ECDSA P-256 signature (ASN.1 DER format) over `message` using
-/// BoringSSL.
-#[must_use]
-pub fn verify_ecdsa_p256_signature(public_key: &[u8], signature: &[u8], message: &[u8]) -> bool {
-    let Some(pk) =
-        bssl_crypto::ecdsa::PublicKey::<bssl_crypto::ec::P256>::from_x962_compressed(public_key)
-    else {
-        return false;
-    };
-    pk.verify(message, signature).is_ok()
-}
-
-/// Dispatches signature verification based on `signature_type`.
-#[must_use]
-pub fn verify_signature(
-    signature_type: SignatureType,
-    public_key: &[u8],
-    signature: &[u8],
-    message: &[u8],
-) -> bool {
-    match signature_type {
-        SignatureType::Ed25519 => verify_ed25519_signature(public_key, signature, message),
-        SignatureType::EcdsaP256SHA256 => {
-            verify_ecdsa_p256_signature(public_key, signature, message)
-        }
-        SignatureType::Unknown => true,
-    }
-}
-
-/// Streaming SHA-512 hasher using BoringSSL.
-pub struct Sha512Hasher {
-    inner: bssl_crypto::digest::Sha512,
-}
-
-impl Default for Sha512Hasher {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-impl Sha512Hasher {
-    pub fn new() -> Self {
-        Self { inner: bssl_crypto::digest::Sha512::new() }
-    }
-
-    pub fn update(&mut self, chunk: &[u8]) {
-        self.inner.update(chunk);
-    }
-
-    pub fn finish(self) -> [u8; 64] {
-        self.inner.digest()
-    }
-}
diff --git a/components/web_package/signed_web_bundles/rust/signed_web_bundles_rust_unittests.rs b/components/web_package/signed_web_bundles/rust/signed_web_bundles_rust_unittests.rs
deleted file mode 100644
index 5516180..0000000
--- a/components/web_package/signed_web_bundles/rust/signed_web_bundles_rust_unittests.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright 2026 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-mod integrity_block_unittest;
diff --git a/components/web_package/signed_web_bundles/rust/types.rs b/components/web_package/signed_web_bundles/rust/types.rs
deleted file mode 100644
index 52d7a84..0000000
--- a/components/web_package/signed_web_bundles/rust/types.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2026 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use alloc::string::String;
-use alloc::vec::Vec;
-
-#[repr(C)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum SignatureType {
-    Ed25519 = 0,
-    EcdsaP256SHA256 = 1,
-    Unknown = 2,
-}
-
-#[repr(C)]
-#[derive(Debug, PartialEq, Clone)]
-pub struct SignatureStackEntry<'a> {
-    pub attributes_cbor: Vec<u8>,
-    pub signature_type: SignatureType,
-    pub public_key: &'a [u8],
-    pub signature: &'a [u8],
-}
-
-#[repr(C)]
-#[derive(Debug, PartialEq, Clone)]
-pub struct IntegrityBlock<'a> {
-    pub size: usize,
-    pub web_bundle_id: &'a str,
-    pub attributes_cbor: Vec<u8>,
-    pub signature_stack: Vec<SignatureStackEntry<'a>>,
-}
-
-#[repr(C)]
-#[derive(Debug, PartialEq, Eq, Clone)]
-pub struct ParseError {
-    pub is_version_error: bool,
-    pub message: String,
-}
-
-impl ParseError {
-    pub(crate) fn format(message: impl Into<String>) -> Self {
-        Self { is_version_error: false, message: message.into() }
-    }
-
-    pub(crate) fn version(message: impl Into<String>) -> Self {
-        Self { is_version_error: true, message: message.into() }
-    }
-}
diff --git a/components/web_package/signed_web_bundles/signed_web_bundle_signature_verifier.cc b/components/web_package/signed_web_bundles/signed_web_bundle_signature_verifier.cc
index 4aef9c4..ff88d0a 100644
--- a/components/web_package/signed_web_bundles/signed_web_bundle_signature_verifier.cc
+++ b/components/web_package/signed_web_bundles/signed_web_bundle_signature_verifier.cc
@@ -20,14 +20,17 @@
 #include "base/task/thread_pool.h"
 #include "base/types/expected.h"
 #include "base/types/expected_macros.h"
+#include "components/cbor/values.h"
+#include "components/cbor/writer.h"
+#include "components/web_package/signed_web_bundles/constants.h"
 #include "components/web_package/signed_web_bundles/identity_validator.h"
 #include "components/web_package/signed_web_bundles/integrity_block_parser.h"
-#include "components/web_package/signed_web_bundles/rust/signed_web_bundles_rust.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_integrity_block.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_signature_stack.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_signature_stack_entry.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_utils.h"
+#include "crypto/hash.h"
 #include "third_party/abseil-cpp/absl/functional/overload.h"
 #include "third_party/boringssl/src/include/openssl/sha.h"
 
@@ -37,10 +40,32 @@ namespace {
 
 std::vector<uint8_t> CreateIntegrityBlockCbor(
     const SignedWebBundleIntegrityBlock& integrity_block) {
-  auto ib_cbor_rust =
-      signed_web_bundles::rust::create_empty_integrity_block_cbor(
-          integrity_block.attributes_cbor());
-  return std::vector<uint8_t>(ib_cbor_rust.begin(), ib_cbor_rust.end());
+  // This function looks like it should use a cbor::Value::ArrayValue to build
+  // the outer array, but it can't: one of the elements is a pre-encoded CBOR
+  // value which we can't safely decode because it's untrusted input. This is
+  // obviously undesirable, because there's no guarantee at all that the
+  // pre-encoded value is actually valid CBOR.
+  //
+  // TODO(https://crbug.com/454485901): once there's a memory-safe CBOR parser,
+  // re-parse the pre-encoded value, then re-encode it here instead of
+  // constructing a CBOR array by hand so that we're guaranteed that the result
+  // of this function is valid.
+  std::vector<uint8_t> ib_cbor;
+
+  // 0x84 is the encoding byte for an array of length 4.
+  ib_cbor.push_back(0x84);
+  base::Extend(ib_cbor,
+               *cbor::Writer::Write(cbor::Value(kIntegrityBlockMagicBytes)));
+  base::Extend(ib_cbor, *cbor::Writer::Write(
+                            cbor::Value(kIntegrityBlockV2VersionBytes)));
+  // We cannot parse `attributes().cbor()` back to a cbor::Value as they
+  // technically represent untrusted input.
+  base::Extend(ib_cbor, integrity_block.attributes_cbor());
+  // Encode an empty signature array.
+  base::Extend(ib_cbor,
+               *cbor::Writer::Write(cbor::Value(cbor::Value::ArrayValue())));
+
+  return ib_cbor;
 }
 
 base::expected<void, SignedWebBundleSignatureVerifier::Error>
@@ -104,7 +129,7 @@ SignedWebBundleSignatureVerifier::CalculateHashOfUnsignedWebBundle(
     return base::unexpected(base::File::ErrorToString(file.GetLastFileError()));
   }
 
-  signed_web_bundles::rust::Sha512Hasher hasher;
+  crypto::hash::Hasher hash(crypto::hash::kSha512);
 
   // Calculate the hash of the Signed Web Bundle excluding its integrity block.
   // The file might be too big to read it into memory all at once, which is why
@@ -121,14 +146,15 @@ SignedWebBundleSignatureVerifier::CalculateHashOfUnsignedWebBundle(
           base::File::ErrorToString(file.GetLastFileError()));
     }
     data.resize(*bytes_read);
-    hasher.update(data);
+    hash.Update(data);
 
     if (!base::CheckAdd(offset, *bytes_read).AssignIfValid(&offset)) {
       return base::unexpected("The Signed Web Bundle is too large.");
     }
   }
 
-  SHA512Digest digest = std::move(hasher).finish();
+  SHA512Digest digest;
+  hash.Finish(digest);
   return digest;
 }
 
diff --git a/components/web_package/signed_web_bundles/signed_web_bundle_utils.cc b/components/web_package/signed_web_bundles/signed_web_bundle_utils.cc
index 6ac2b51..9258161 100644
--- a/components/web_package/signed_web_bundles/signed_web_bundle_utils.cc
+++ b/components/web_package/signed_web_bundles/signed_web_bundle_utils.cc
@@ -5,18 +5,37 @@
 #include "components/web_package/signed_web_bundles/signed_web_bundle_utils.h"
 
 #include <cstdint>
-#include <vector>
 
-#include "components/web_package/signed_web_bundles/rust/signed_web_bundles_rust.h"
+#include "base/containers/extend.h"
+#include "base/containers/span.h"
+#include "base/containers/span_writer.h"
 
 namespace web_package {
 
+namespace {
+
+void AddItemToPayload(std::vector<uint8_t>& payload,
+                      base::span<const uint8_t> item) {
+  // Each item that is part of the payload is prefixed with its length encoded
+  // as a 64 bit unsigned integer.
+  std::array<uint8_t, sizeof(uint64_t)> length;
+  auto writer = base::SpanWriter(base::span(length));
+  CHECK(writer.WriteU64BigEndian(item.size()));
+
+  base::Extend(payload, base::span(length));
+  base::Extend(payload, item);
+}
+
+}  // namespace
+
 std::vector<uint8_t> CreateSignaturePayload(
     const SignedWebBundleSignatureData& data) {
-  auto payload_rust = signed_web_bundles::rust::create_signature_payload(
-      data.unsigned_web_bundle_hash, data.integrity_block_cbor,
-      data.attributes_cbor);
-  return std::vector<uint8_t>(payload_rust.begin(), payload_rust.end());
+  std::vector<uint8_t> payload;
+  AddItemToPayload(payload, data.unsigned_web_bundle_hash);
+  AddItemToPayload(payload, data.integrity_block_cbor);
+  AddItemToPayload(payload, data.attributes_cbor);
+
+  return payload;
 }
 
 }  // namespace web_package
