はじめに:突然のサービス終了通知
2025年8月某日、田中さん(仮名・ITエンジニア)のもとにDropboxから予想外の通知が届きました。
重要:Dropbox Passwordsは2025年10月28日をもってサービスを終了いたします
私のDropbox Passwordsには723件のパスワードが保存されている。残された時間は約2ヶ月。これは緊急事態だった。
第1章:インポート失敗の現実
Dropboxの案内では1Password(有料)への移行を推奨していたが、私は無料のGoogleパスワードマネージャーを選択。CSVエクスポート機能を使えば簡単に移行できるはずだった。
結果:
323件のパスワードをインポートしました
400件のパスワードをインポートできませんでした
なんと55%もインポートに失敗! 幸い、Googleのエラーメッセージは明確で、失敗の原因はすぐに判明した。
第2章:問題の本質
Googleパスワードマネージャーのエラーメッセージが教えてくれた原因:
問題1:URL未設定問題(最重要)
import pandas as pd
df = pd.read_csv('exported_dropbox_accounts.csv')
missing_urls = df[df['website'].isna() | (df['website'] == '')]
print(f"URLが空欄のエントリ: {len(missing_urls)}件")
# 結果: 392件!
392件(54%)でURLが未設定。 Googleパスワードマネージャーは、URLが設定されていないエントリを受け付けない仕様だった。
問題2:メモ文字数制限
複数のエントリでメモが1,000文字を超えており、Googleの制限に引っかかった。
第3章:AI活用の選択
ここで3つの選択肢があった:
- 選択肢A: 完全手動(安全だが392件を手動調査は非現実的)
- 選択肢B: パスワード匿名化+AI活用(今回の選択)
- 選択肢C: 全データをAIに見せる(最も簡単だがリスク大)
私は選択肢Bを選択。パスワードは絶対に見せたくないが、サービス名程度なら許容し、自動化による正確性を重視した。
補足: 生成AIの学習データ利用を気にしない人は、選択肢Cで直接処理してもよい。個人の判断次第。
第4章:3段階セキュア移行システム
アーキテクチャ
元CSV(723件) Step1匿名化 Step2 URL生成 Step3復元 最終CSV
パスワード含む → パスワード除去 → Claude活用 → パスワード再結合 → Google対応
Step 1:パスワード匿名化
import hashlib
import pandas as pd
def anonymize_passwords(input_csv, output_csv):
df = pd.read_csv(input_csv)
# パスワードをハッシュベースのダミー値に置換
df['password'] = df['password'].apply(
lambda x: f"DUMMY_{hashlib.md5(str(x).encode()).hexdigest()[:8]}"
)
df.to_csv(output_csv, index=False, encoding='utf-8')
return df
ポイント: パスワードは完全匿名化され復元不可能だが、インデックスは保持される。
Step 2:Claude活用によるURL生成
392件の多様なサービス名から適切なURLを生成:
# 実際のサービス名例
service_names = [
"楽天", "SBI証券:取引パスワード", "JALマイレージ",
"ムームードメイン", "さくらのVPS", "192.168.1.1"
]
# Claude判断例:
# "楽天" → "https://www.rakuten.co.jp/"
# "SBI証券:取引パスワード" → "https://www.sbisec.co.jp/"
# "192.168.1.1" → "https://192.168.1.1/"
この段階では392件のURLを生成できたが、実際に正しいかどうかは後の検証でわかることになる。
Step 3:パスワード復元
def restore_passwords(original_csv, anonymized_csv, output_csv):
original_df = pd.read_csv(original_csv)
completed_df = pd.read_csv(anonymized_csv)
# インデックスベースで元のパスワードを復元
for index in completed_df.index:
if index < len(original_df):
completed_df.at[index, 'password'] = original_df.at[index, 'password']
completed_df.to_csv(output_csv, index=False, encoding='utf-8')
第5章:追加の技術的課題
Googleの隠れた制約
- URLフォーマット要件:
https://プレフィックス必須 - メモ制限: 1,000文字(空白・改行含む)
- エラーメッセージ: どのエントリが失敗したか不明
対策
def fix_common_issues(df):
for index, row in df.iterrows():
url = row['website']
# IPアドレス処理
if re.match(r'^\d+\.\d+\.\d+\.\d+$', url):
df.at[index, 'website'] = f'https://{url}/'
# プロトコル追加
elif not url.startswith('http'):
df.at[index, 'website'] = f'https://www.{url}'
# メモ制限対応
df['notes'] = df['notes'].str[:1000]
return df
結果:100%完全移行達成
最終的に:
723件のパスワードをインポートしました
0件のパスワードをインポートできませんでした
- 処理時間: 約2時間
- URL補完: 392件
- 手動介入: ゼロ
教訓
1. セキュリティファースト
# 🔴 NG: パスワード直接処理
password_list = ["actual_password_123"]
# 🟢 推奨: 匿名化処理
password_list = ["DUMMY_a1b2c3d4"]
2. AI活用の判断基準
AIに見せてもOK: サービス名、ユーザー名、一般的なメタデータ
見せるべきでない: パスワード本体、秘密の質問、2FA情報
グレーゾーン: メモ内容(個人判断)
3. 移行プロジェクトの鉄則
- バックアップは3重に
- 段階的アプローチ(10件→100件→全件)
- 失敗前提の設計
まとめ
パスワード移行という極めてセンシティブな作業でも、適切な匿名化とアーキテクチャ設計により、AIを安全に活用できることを実証できた。
重要なのは、自分のリスク許容度に応じた選択をすること。
Dropbox Passwordsのような突然のサービス終了は誰にでも起こりうる。定期的なバックアップと移行計画の準備を強く推奨する。
この記事が、同じ悩みを抱える誰かの助けになれば幸いです。