· Nacho Coll · Guides  · 14 分で読了

IPFS CID の解説:その正体とコンテンツアドレッシングの仕組み

IPFS Content Identifier (CID) の明快な技術解説。コンテンツアドレッシングの仕組み、CID のバージョン、最初の CID の作成方法まで。

IPFS Content Identifier (CID) の明快な技術解説。コンテンツアドレッシングの仕組み、CID のバージョン、最初の CID の作成方法まで。

IPFS (InterPlanetary File System) を扱ったことがあるなら、QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdGbafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi のような文字列を目にしたことがあるはずです。これはランダムな羅列ではなく、Content Identifier (CID) — IPFS のコンテンツアドレッシングシステムの中核 — です。

CID を理解することは、IPFS の上に何かを構築する人にとって不可欠です。ファイルをアップロードする場合でも、分散型アプリケーションを構築する場合でも、コンテンツ配信システムを実装する場合でも同じです。本ガイドでは、IPFS の CID について知っておくべきことすべて、コンテンツアドレッシングの仕組み、そしてあなたのプロジェクトでの使い始め方を分解して解説します。

IPFS Ninja

IPFS CID とは

Content Identifier (CID) は、IPFS 上のコンテンツを表す一意の指紋です。場所を指す従来の Web URL (例:https://example.com/file.pdf) とは異なり、CID はそれが保管されている場所に関係なくコンテンツそのものを指します。

こう考えてください:

  • 場所ベースのアドレッシング:「メイン通り 123 番地に行って赤い本を聞いてください」
  • コンテンツベースのアドレッシング:「ISBN 978-0-123456-78-9 の本を見つけてください」(どこの図書館にあるかは問わない)

CID も同様に動作します — 暗号学的ハッシュによってコンテンツを識別し、コンテンツを不変かつ検証可能にします。ファイルの 1 バイトでも変われば、CID は完全に変わります。

コンテンツアドレッシングが重要な理由

従来の Web アーキテクチャは場所ベースのアドレッシングに依存しています。https://example.com/image.jpg を訪れるとき、あなたは次のことを信頼しています:

  1. ドメイン所有者がコンテンツを変えていない
  2. サーバーがオンラインで到達可能である
  3. コンテンツが改ざんされていない

CID によるコンテンツアドレッシングでは:

  1. 不変性:CID は内容が変わっていないことを保証
  2. 分散化:CID を持つどの IPFS ノードからもコンテンツを取得可能
  3. 検証:受信したコンテンツが正しいかを暗号学的に検証可能
  4. 効率性:同一のコンテンツは自動で重複排除される

CID の構造

典型的な CID を分解して、その構成要素を理解しましょう:

bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi
└─┬─┘└─────────────────┬─────────────────────────────────┘
  │                   │
  │                   └─ コンテンツのハッシュ (Base32 エンコード)
  └─ Multibase プレフィックス (エンコーディングを示す)

CID にはいくつかの情報が含まれます:

1. Multibase プレフィックス

最初の文字が CID のエンコーディングを示します:

  • Q = Base58 エンコーディング (CIDv0)
  • b = Base32 エンコーディング (CIDv1)
  • f = Base16/16 進数 (CIDv1)
  • z = Base58 (CIDv1)

2. CID のバージョン

  • CIDv0:常に Qm で始まり、SHA-256 を使用し、DAG-PB コーデックに限定
  • CIDv1:より柔軟で、複数のハッシュ関数とコーデックをサポート

3. Multicodec

コンテンツがどのように構造化されているかを指定します (DAG-PB、DAG-CBOR、生バイトなど)

4. Multihash

コンテンツの実際の暗号学的ハッシュで、以下を含みます:

  • ハッシュ関数の識別子 (通常は SHA-256)
  • ハッシュの長さ
  • ハッシュダイジェスト

CIDv0 と CIDv1:違いを理解する

IPFS は 2 つの主要な CID バージョンを経て進化してきました。それぞれ異なる特性を持ちます:

CIDv0:オリジナル形式

CIDv0 の CID は常に Qm で始まり、こんな見た目です:

QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG

特性:

  • Base58 エンコーディングのみ
  • SHA-256 ハッシュ関数のみ
  • DAG-PB (Protobuf) コーデックのみ
  • 46 文字の長さ
  • すべての IPFS 実装と後方互換

CIDv0 を使う場面:

  • 古い IPFS ノードとの最大限の互換性
  • Qm プレフィックスを期待する既存システムとの連携
  • ファイル保管 (最も一般的なユースケース)

CIDv1:モダンな標準

CIDv1 の CID はより柔軟で、こんな見た目になり得ます:

bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi  # Base32
zb2rhj7crUKTQYRGCRATFaQ6YFLTde2YzdqbbhAASkL9uRDXn      # Base58
f01551220d1e2c35...                                      # Base16

特性:

  • 複数のエンコーディング形式 (Base32、Base58、Base16)
  • 異なるハッシュ関数のサポート (SHA-256、SHA-512、BLAKE2 など)
  • 複数のコーデック (Raw、DAG-CBOR、DAG-JSON など)
  • 自己記述的な形式
  • Base32 使用時は大文字小文字を区別しない

CIDv1 を使う場面:

  • 新しいアプリケーションの構築
  • 大文字小文字を区別しない識別子が必要な場合
  • 構造化データ (JSON、CBOR) の取り扱い
  • 代替ハッシュ関数の使用

バージョン間の変換

同じコンテンツ参照を維持したまま、CID をバージョン間で変換できます:

// CIDv0
const cidv0 = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG";

// Convert to CIDv1 Base32
const cidv1 = "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi";

// Both reference the same content!

コンテンツアドレッシングの仕組み

IPFS のコンテンツアドレッシングは、同じコンテンツが常に同じ CID を生成することを保証する決定論的なプロセスに従います:

1. コンテンツの準備

IPFS にコンテンツを追加すると、まず分解されます:

  • 小さなファイル:単一のブロックとして保管
  • 大きなファイル:チャンクに分割され、Merkle DAG (Directed Acyclic Graph) に組織化
  • ディレクトリ:ファイルにリンクする DAG 構造として表現

2. ハッシング処理

各コンテンツは以下を経由します:

  1. シリアライズ:コンテンツがコーデックに従ってフォーマットされる
  2. ハッシング:暗号学的ハッシュ関数がシリアライズされたデータを処理
  3. Multihash 作成:ハッシュがアルゴリズムと長さの情報でラップされる
  4. CID 組み立て:バージョン、コーデック、Multihash が結合される

3. Merkle DAG 構造

IPFS は Merkle DAG でコンテンツを組織化します。そこでは:

  • 各ノードが CID を持つ
  • 親ノードは CID で子ノードを参照
  • ノードへの変更は木の上方に伝播
  • 構造全体を暗号学的に検証可能
Root CID: bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi
├── file1.txt (QmHash1...)
├── file2.jpg (QmHash2...)
└── subdirectory/
    ├── file3.pdf (QmHash3...)
    └── file4.mp4 (QmHash4...)

実践例:CID を扱う

IPFS Ninja の API を使って実際に CID を扱う方法を見てみましょう:

コンテンツのアップロードと CID の取得

// Upload a file and get its CID
const uploadFile = async (content, filename) => {
  const response = await fetch('https://api.ipfs.ninja/upload/new', {
    method: 'POST',
    headers: {
      'X-Api-Key': 'bws_1234567890abcdef1234567890abcdef12345678',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      content: btoa(content), // Base64 encode binary content
      description: `Upload of ${filename}`
    })
  });
  
  const result = await response.json();
  console.log('CID:', result.cid);
  console.log('IPFS URL:', result.uris.ipfs);
  console.log('HTTP URL:', result.uris.url);
  
  return result.cid;
};

// Example usage
uploadFile('Hello, IPFS!', 'greeting.txt');
// Returns: bafkreifjxz6zwqh27k5xnr5qfbx4w6n5vuwwwdcngguwjewzj2e3xxfgvi

既存コンテンツの CID による pin

すでに CID を持っているなら、それを pin して可用性を確保できます:

const pinByCID = async (cid) => {
  const response = await fetch('https://api.ipfs.ninja/pin', {
    method: 'POST',
    headers: {
      'X-Api-Key': 'bws_1234567890abcdef1234567890abcdef12345678',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      cid: cid,
      description: 'Pinned via API'
    })
  });
  
  const result = await response.json();
  console.log('Pinned CID:', result.cid);
  
  return result;
};

// Pin the "Hello World" of IPFS
pinByCID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u');

CID 経由でコンテンツにアクセス

CID があれば、コンテンツへは複数の方法でアクセス可能です:

// Direct IPFS gateway access
const ipfsUrl = `https://ipfs.ninja/ipfs/${cid}`;

// Custom gateway (if configured)
const customGatewayUrl = `https://my-app.gw.ipfs.ninja/ipfs/${cid}`;

// Fetch content programmatically
const fetchContent = async (cid) => {
  const response = await fetch(`https://ipfs.ninja/ipfs/${cid}`);
  const content = await response.text();
  return content;
};

開発者向け CID のベストプラクティス

1. 常に CID を検証する

アプリケーションで CID を使う前に、その形式を検証してください:

const isValidCID = (cid) => {
  // Basic validation patterns
  const cidv0Pattern = /^Qm[1-9A-HJ-NP-Za-km-z]{44}$/;
  const cidv1Pattern = /^[bf][a-z2-7]{58}$/;
  
  return cidv0Pattern.test(cid) || cidv1Pattern.test(cid);
};

2. 両方の CID バージョンを扱う

アプリケーションは CIDv0 と CIDv1 の両方で動作すべきです:

const normalizeCID = (cid) => {
  if (cid.startsWith('Qm')) {
    // CIDv0 - can convert to CIDv1 if needed
    return cid;
  } else if (cid.startsWith('b') || cid.startsWith('f') || cid.startsWith('z')) {
    // CIDv1
    return cid;
  } else {
    throw new Error('Invalid CID format');
  }
};

3. CID のマッピングをキャッシュする

頻繁に CID を生成するなら、キャッシュを検討してください:

const cidCache = new Map();

const getCachedCID = (content) => {
  const contentHash = btoa(content);
  
  if (cidCache.has(contentHash)) {
    return cidCache.get(contentHash);
  }
  
  // Upload and cache result
  return uploadFile(content).then(cid => {
    cidCache.set(contentHash, cid);
    return cid;
  });
};

4. 意味のある説明を使用する

コンテンツをアップロードする際は、記述的なメタデータを含めましょう:

const uploadWithMetadata = async (content, metadata) => {
  return fetch('https://api.ipfs.ninja/upload/new', {
    method: 'POST',
    headers: {
      'X-Api-Key': 'bws_1234567890abcdef1234567890abcdef12345678',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      content: btoa(content),
      description: metadata.name || 'Uploaded file',
      metadata: {
        filename: metadata.filename,
        contentType: metadata.contentType,
        uploadedAt: new Date().toISOString(),
        version: metadata.version || '1.0'
      }
    })
  });
};

CID のよくあるユースケース

1. 静的ウェブサイトのデプロイ

ウェブサイト全体を IPFS にデプロイし、CID で参照します:

// Upload website directory structure
const deployWebsite = async (files) => {
  const uploads = await Promise.all(
    files.map(file => uploadFile(file.content, file.path))
  );
  
  // Root CID references entire site
  const rootCID = uploads.find(u => u.path === 'index.html').cid;
  console.log(`Website deployed: https://ipfs.ninja/ipfs/${rootCID}`);
  
  return rootCID;
};

ウェブサイトのデプロイについて詳しくは、IPFS にファイルをアップロードする方法のガイドをご覧ください。

2. NFT メタデータの保管

CID を使って NFT メタデータを不変に保管します:

const nftMetadata = {
  name: "My Awesome NFT",
  description: "A unique digital collectible",
  image: "ipfs://bafkreibc5sgo2plmjkq2tzmhrn54bk3crhnqekiy7u66fqvqm37pu2e5gw",
  attributes: [
    { trait_type: "Color", value: "Blue" },
    { trait_type: "Rarity", value: "Epic" }
  ]
};

const metadataCID = await uploadFile(
  JSON.stringify(nftMetadata, null, 2), 
  'metadata.json'
);

// Use in smart contract
console.log(`Token URI: ipfs://${metadataCID}`);

3. コンテンツ配信

CID を分散コンテンツ配信に使います:

// Upload once, access everywhere
const distributeContent = async (content) => {
  const cid = await uploadFile(content, 'content.txt');
  
  // Content available via multiple gateways
  const gateways = [
    `https://ipfs.ninja/ipfs/${cid}`,
    `https://ipfs.io/ipfs/${cid}`,
    `https://cloudflare-ipfs.com/ipfs/${cid}`
  ];
  
  return { cid, gateways };
};

CID と IPFS ピン留めを理解する

CID はデフォルトでは一時的です — 「ピン留め」する必要があります。詳しくはIPFS ピン留めとは何かの包括的なガイドをご覧ください。

IPFS のピン留めサービスを選ぶときは、IPFS Ninja vs Pinata の比較を読むか、現在利用可能な最高の IPFS ピン留めサービス のまとめをご覧ください。

30 秒で最初の CID を作成する

最初の CID を生成する準備はできましたか? IPFS Ninja の API を使った簡単な例です:

# Using curl (replace with your actual API key)
curl -X POST https://api.ipfs.ninja/upload/new \
  -H "X-Api-Key: bws_YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "SGVsbG8sIElQRlMgV29ybGQh",
    "description": "My first IPFS upload"
  }'
// Using JavaScript
const createFirstCID = async () => {
  const response = await fetch('https://api.ipfs.ninja/upload/new', {
    method: 'POST',
    headers: {
      'X-Api-Key': 'bws_YOUR_API_KEY_HERE',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      content: btoa('Hello, IPFS World!'), // Base64: "SGVsbG8sIElQRlMgV29ybGQh"
      description: 'My first IPFS upload'
    })
  });
  
  const result = await response.json();
  console.log('🎉 Your first CID:', result.cid);
  console.log('🌐 Access it at:', result.uris.url);
  
  return result;
};

createFirstCID();

これは以下のようなものを返します:

{
  "cid": "bafkreif2pall7dybz7vecqka3zo24irdwabf7rbiiweuhau7a2hjlqvfjw",
  "sizeMB": 0.000017,
  "uris": {
    "ipfs": "ipfs://bafkreif2pall7dybz7vecqka3zo24irdwabf7rbiiweuhau7a2hjlqvfjw",
    "url": "https://ipfs.ninja/ipfs/bafkreif2pall7dybz7vecqka3zo24irdwabf7rbiiweuhau7a2hjlqvfjw"
  }
}

さらに詳しい API の例は、IPFS アップロード API チュートリアルをご覧ください。

まとめ

CID は IPFS のコンテンツアドレッシングシステムの基盤であり、不変で、検証可能で、分散化されたコンテンツ識別を提供します。CIDv0 vs CIDv1 の技術的詳細から実用的な実装パターンまで、それらがどう機能するかを理解することは、堅牢な分散アプリケーションを構築する上で不可欠です。

要点:

  • CID は場所ではなくコンテンツを一意に識別する
  • CIDv0 は最大限の互換性を提供し、CIDv1 は柔軟性を提供する
  • コンテンツアドレッシングは検証と重複排除を可能にする
  • 適切な CID 処理は本番アプリケーションに不可欠

NFT メタデータを保管する場合も、分散ウェブサイトをデプロイする場合も、コンテンツ配信システムを構築する場合も、CID は真に分散化されたアプリケーションに必要な信頼できる基盤を提供します。

ピン留めを始める準備はできましたか? 無料アカウントを作成 — 50 ファイル、ストレージ 1 GB、月 2 GB の帯域。クレジットカード不要。

ブログに戻る