> For the complete documentation index, see [llms.txt](https://help.keyring.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.keyring.app/jp/keyring-pro/punssu.md).

# オープンソース

## KEYRING PROはオープンソースです

[**KEYRING PROの公開リポジトリを見る**](https://github.com/bacoor-hb/KEYRINGPRO)

{% embed url="<https://github.com/bacoor-hb/KEYRINGPRO>" %}

信頼は透明性から始まります。

<mark style="color:$success;">KEYRING PROは、ユーザーが秘密鍵と資産を完全に管理できるノンカストディアルウォレットです</mark>。ウォレットは非常に機密性の高い情報を取り扱うため、ユーザーに必要なのは、単なるセキュリティ上の主張だけではないと考えています。資産を保護する技術を第三者が独立して確認し、検証できるという確信が必要です。

KEYRING PROをオープンソースとして公開することで、開発者、セキュリティ専門家、監査担当者、組織が、ウォレットの仕組みを確認できるようにしています。秘密鍵がどのように生成・暗号化され、どこに保存されるのか、ウォレットへのアクセスがどのように保護されるのか、バックアップファイルがどのように保護されるのか、トランザクションがどのように署名されるのかを確認できます。

多くのユーザーが、自分でソースコードを読む必要はないかもしれません。しかし、実装が一般公開されていることで、KEYRING PROが透明性と検証可能性のあるセキュリティ原則に基づいて構築されているという、より高い信頼を得ることができます。

オープンソースは、私たちの説明責任への取り組みも示しています。KEYRING PROが説明する保護機能は、それを実装している実際のコードと直接比較できます。ユーザーは、非公開の仕組みや根拠のない約束だけを信頼する必要はありません。

ソースコードを公開しても、ユーザーの秘密鍵、パスワード、バックアップファイル、残高、その他の個人的なウォレット情報が公開されることはありません。これらの情報は実際にウォレットを使用する際に作成され、公開されているソースコードとは分離されています。本番環境用の認証情報やサービスキーも、公開リポジトリには含まれていません。

KEYRING PROにとってオープンソースとは、単にコードを公開することではありません。透明性、説明責任、独立して検証可能なセキュリティを通じて、ユーザーがより高い信頼を持って利用できるウォレットを構築するという、私たちの約束です。

> <mark style="color:pink;">**セキュリティは、盲目的な信頼に依存すべきではありません。透明性があり、検証可能であり、ユーザーが安心して利用できるように構築されるべきです。**</mark>

## KEYRING PROが資産を保護する仕組み

KEYRING PROにおける秘密鍵の保護は、次の明確な流れに従っています。

* 安全な暗号学的ランダム性を使用して秘密鍵を生成します。
* ユーザーのパスワードから導出された鍵を使用して秘密鍵を暗号化します。
* 保護された秘密鍵をユーザーの端末内にローカル保存します。
* ウォレットがロック解除されている場合にのみ、秘密鍵を取得して復号します。
* トランザクションはウォレット内部で署名されます。
* 署名済みトランザクションのみがブロックチェーンネットワークへ送信されます。

ソースコードが公開されているため、この処理の各段階を直接確認できます。

### <mark style="color:red;">ノンカストディアル。秘密鍵は端末内にローカル保存されます</mark>

パスワード保護が有効な場合、KEYRING PROは秘密鍵を保存する前に暗号化します。

```js
let value = privateKey
if (vaultHasPassword()) {
  if (!vaultIsUnlocked()) {
    vaultRequestUnlock()
    return false
  }
  value = vaultEncryptPrivateKey(privateKey)
}
```

保護された値は、ウォレットアドレスごとに保存されます。

```js
listPrivateKeyByAddress[lowerCase(address)] = value
storeDataToSecureStorage(KEYSTORE.LIST_PRIVATE_KEY_BY_ADDRESS, listPrivateKeyByAddress)
```

`storeDataToSecureStorage()`は、保護されたデータをユーザー端末上のアプリケーション内にあるMMKVストレージ領域へ書き込みます。

```js
secureStorage = new MMKV({
  id: Config.SECURE_STORAGE_ID,
  encryptionKey
})
```

```js
secureStorage.set(key, JSON.stringify(value))
```

MMKVストレージ領域自体も暗号化キーを使用して開かれます。通常の初期設定処理では、アプリケーションは端末のOSキーチェーンを通じて、このストレージキーを取得します。

これらの関数は、ローカルストレージへの保存処理を行います。秘密鍵をKEYRING PROのサーバーへアップロードするネットワークリクエストは含まれていません。

> <mark style="color:green;">**秘密鍵は、ユーザー自身の端末内にある保護されたアプリケーションストレージへ保存されます。KEYRING PROは、ウォレットを管理するための秘密鍵のコピーをサーバー側に保管しません。**</mark>
>
> <mark style="color:green;">**これにより、秘密鍵はKEYRING PROや他のサービスではなく、ユーザー自身の端末上で管理されます。**</mark>

### 安全な秘密鍵生成

「秘密鍵を自動生成」を選択すると、KEYRING PROはViemのアカウントライブラリからインポートされた2つのメソッドを使用します。

```js
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
```

秘密鍵が生成され、EthereumおよびEVMアカウントへ変換されます。

```js
const privateKey = generatePrivateKey()
const account = privateKeyToAccount(privateKey)
```

`generatePrivateKey()`は、新しいランダムな秘密鍵を生成します。`privateKeyToAccount()`は、その秘密鍵から対応するEthereumおよびEVMウォレットアドレスを導出します。

Viemは、セキュリティを重視した暗号ライブラリ`@noble/curves`のsecp256k1実装を使用して秘密鍵を生成します。secp256k1は、Ethereumのアカウントキーに使用される楕円曲線です。

KEYRING PROは、React Native環境で暗号学的に安全なシステムランダム値を提供する`react-native-get-random-values`も読み込みます。これは、一般的なアプリケーション処理で使用される通常のランダム関数とは異なります。

> <mark style="color:green;">**自動生成される秘密鍵は、安全なシステムランダム性から作成され、EthereumおよびEVMネットワークで使用される暗号モデルに従っています。単純または予測可能なパターンに基づいていないため、第三者が推測または再現することは極めて困難です。**</mark>
>
> <mark style="color:green;">**これにより、秘密鍵を極めて推測困難にし、不正アクセスからウォレットを保護します。**</mark>

KEYRING PROは、秘密鍵の手動生成にも対応しており、ウォレットアカウントを作成する際に、より柔軟で直接的な管理が可能です。

この方法では、数字の0～9とアルファベットのA～Fを使用した、有効な64文字の16進数を入力して秘密鍵を作成できます。

最も高い保護レベルを確保するため、自分だけが知っている、推測が困難で固有の組み合わせを使用してください。

### 秘密鍵のパスワード保護

KEYRING PROは、ユーザーのパスワードをそのまま暗号化キーとして使用しません。

代わりに、`react-native-quick-crypto`ライブラリが提供する暗号処理を使用します。

```js
import QuickCrypto from 'react-native-quick-crypto'
```

パスワード処理と暗号化の設定は次のとおりです。

```js
export const PBKDF2_ITERATIONS_DEFAULT = 900000
export const KEY_LENGTH = 32
```

```js
export const DIGEST = 'sha512'
export const CIPHER_ALGO = 'aes-256-gcm'
```

パスワードは、PBKDF2-SHA512を使用して900,000回処理されます。これにより、機密性の高いウォレットデータを保護するための256ビット暗号化キーが生成されます。

PBKDF2は、最終的な暗号化キーを生成する前に、パスワードを繰り返し処理します。各ウォレットではsaltと呼ばれるランダムな値も使用されるため、同じパスワードを使用しても、異なるデータに対して常に同じ暗号化結果が生成されるわけではありません。

生成された暗号化キーは、AES-256-GCMで使用されます。

```js
const cipher = QuickCrypto.createCipheriv(CIPHER_ALGO, key, iv)
const ciphertext = Buffer.concat([cipher.update(Buffer.from(plaintext, 'utf8')), cipher.final()])
const tag = cipher.getAuthTag()
```

AES-256-GCMは、秘密鍵を読み取ることのできない暗号化データへ変換します。また、暗号化された情報が変更または破損していないことをウォレットが確認するための認証タグも生成します。

次の場合、復号に失敗します。

* パスワードから誤った暗号化キーが生成された場合
* 暗号化データが変更されている場合
* 認証タグが一致しない場合
* 保存データが破損している場合

> <mark style="color:green;">**パスワード保護が有効な場合、秘密鍵は読み取り可能なテキストとして保存されません。復号には正しいパスワードから導出されたキーが必要であり、暗号化データが変更または破損している場合はセキュリティチェックに失敗します。**</mark>
>
> <mark style="color:green;">**これにより、正しいパスワードがなければ秘密鍵を読み取ることができず、暗号化データの変更や破損も検出できます。**</mark>

強力で固有のパスワードを使用することは、引き続き重要です。暗号化によってパスワードの推測は大幅に困難になりますが、簡単に推測できるパスワードを完全に安全にすることはできません。

### 秘密鍵は通常のアカウントデータから分離されます

アカウントが作成またはインポートされると、KEYRING PROは秘密鍵を専用の秘密鍵ストレージへ移動し、通常のアカウントオブジェクトから削除します。

```js
// store private key to secure storage
storePrivateKeyByAddress(evmAccount.address, evmAccount.privateKey)
// remove private key from object
delete evmAccount.privateKey
```

ウォレットアドレス、アカウント名、選択したネットワーク、その他の一般情報は、通常のウォレット画面で引き続き使用できます。秘密鍵は、これらのアカウント情報とは分離して保存されます。

KEYRING PROは、アプリケーションのすべての部分に秘密鍵を保持することなく、ウォレットアドレス、残高、トランザクション情報を表示できます。これにより、ウォレット内で最も機密性の高い情報への不要なアクセスを減らします。

> <mark style="color:green;">**秘密鍵は通常のアカウントデータから削除され、保護された専用の秘密鍵ストレージへ分離して保存されます。**</mark>
>
> <mark style="color:green;">**これにより、秘密鍵へのアクセスは、本当に必要なウォレット機能のみに制限されます。**</mark>

### 秘密鍵は必要な場合にのみ取得されます

KEYRING PROが認証済みの操作で秘密鍵を必要とする場合、まずローカルのセキュアストレージから保護されたエントリを読み込みます。

```js
const listPrivateKeyByAddress = getDataFromSecureStorage(KEYSTORE.LIST_PRIVATE_KEY_BY_ADDRESS, {})
const entry = listPrivateKeyByAddress?.[lowerCase(address)]
```

エントリが暗号化されている場合、KEYRING PROは保管領域がロック解除されているか確認します。

```js
if (isEncryptedEntry(entry)) {
  if (!vaultIsUnlocked()) {
    vaultRequestUnlock()
    return ''
  }
  try {
    privateKey = vaultDecryptPrivateKey(entry)
  } catch (e) {
    return ''
  }
}
```

ウォレットがロックされている場合、秘密鍵は返されません。ユーザーは最初にロック解除処理を完了する必要があります。

KEYRING PROは、復号された秘密鍵を常時利用可能な状態で保持しません。保護されたウォレット操作で必要となり、ウォレットが正常にロック解除されている場合にのみ、秘密鍵を取得して復号します。

> <mark style="color:green;">**暗号化された秘密鍵は、ウォレットが正常にロック解除された後にのみ取得できます。ウォレットがロックされている場合、または復号に失敗した場合、秘密鍵は返されません。**</mark>
>
> <mark style="color:green;">**これにより、秘密鍵は必要な場合にのみアクセスされ、不要な露出が抑えられます。**</mark>

### 有効な保管領域キーは一時的です

正しいパスワードが入力されると、KEYRING PROは導出された保管領域キーを、一時的にアプリケーションのアクティブな状態へ保持します。

```js
// RAM-only. Never persisted.
let vaultEncryptionKey = null
```

保管領域キーにより、ウォレットがロック解除されている間、認証済みの秘密鍵操作を実行できます。このモジュールは、このキーを永続的な値として保存しません。

ウォレットがロックされると、アクティブな参照が消去されます。

```js
export const clearVault = () => {
  vaultEncryptionKey = null
}
```

同じモジュールは、保管領域がロックされている間の暗号化を拒否します。

```js
export const encryptPrivateKey = (plainPk) => {
  if (!vaultEncryptionKey) throw new Error('Vault is locked')
  return encryptWithKey(plainPk, vaultEncryptionKey)
}
```

復号も同じ要件で保護されます。

```js
export const decryptPrivateKey = (entry) => {
  if (!vaultEncryptionKey) throw new Error('Vault is locked')
  return decryptWithKey(entry, vaultEncryptionKey)
}
```

これにより、保管領域がロックされた後も、通常のウォレット処理を通じて保護された秘密鍵操作が継続されることを防ぎます。

> <mark style="color:green;">**暗号化された秘密鍵へアクセスできるのは、ウォレットが正常にロック解除されている間だけです。ウォレットがロックされると、有効な保管領域キーは消去され、再度認証が必要になります。**</mark>
>
> <mark style="color:green;">**これにより、ウォレットがロックされた後も、保護されたウォレット機能へアクセスし続けることを防ぎます。**</mark>

### トランザクションはウォレット内部で署名されます

ユーザーがトランザクションを承認すると、KEYRING PROはアプリケーション内部の秘密鍵を使用して署名済みトランザクションを作成します。

```js
const signedTransaction = await ethWallet.signTransaction(rawTransaction)
```

秘密鍵は、トランザクションをローカルで承認するために使用されます。秘密鍵自体がトランザクションデータへ追加されることはありません。

完成した署名済みトランザクションは、その後ブロードキャスト処理へ送られます。

```js
this.sendSignedTransactionWithRetry(chainTypeOrChainId, signedTransaction, isWaitDone, callback)
  .then(result => resolve(result))
  .catch(err => reject(err))
```

つまり、秘密鍵はアカウント所有者がトランザクションを承認したことを示す暗号学的証明を作成するために使用されますが、秘密鍵自体をウォレット外へ送信する必要はありません。

> <mark style="color:green;">**秘密鍵は、トランザクションを承認するために端末内で使用されます。署名処理の一部として、ブロックチェーンサービスへ送信されることはありません。**</mark>
>
> <mark style="color:green;">**これにより、秘密鍵をウォレット外へ送信せずにトランザクションを承認できます。**</mark>

### 署名済みトランザクションのみがブロードキャストされます

ローカルでの署名が完了すると、KEYRING PROはシリアライズされた署名済みトランザクションをRPCサービスへ送信します。

```js
const hash = await client.sendRawTransaction({ serializedTransaction: signedTransaction })
```

RPCサービスは、署名済みトランザクションを使用してブロックチェーンへ処理をブロードキャストします。署名を作成した秘密鍵は必要ありません。

> <mark style="color:green;">**ブロックチェーンインフラストラクチャが受け取るのは署名済みトランザクションであり、ウォレットアカウントを管理する秘密鍵ではありません。**</mark>
>
> <mark style="color:green;">**これにより、ブロックチェーンは秘密鍵を受け取ることなくトランザクションを処理できます。**</mark>

### ソースコードによって確認できるセルフカストディ

公開されたコードでは、秘密鍵の完全な処理フローを確認できます。

**安全なランダム性 → 秘密鍵生成 → パスワードベースの暗号化 → 端末内へのローカル保存 → 認証後の復号 → ローカルでのトランザクション署名 → 署名済みトランザクションのブロードキャスト**

KEYRING PROは、アカウントの作成、秘密鍵の保存、ウォレットのロック解除、トランザクションのブロードキャストを行うために、秘密鍵のコピーをサーバー側へ保持する必要がありません。

公開ウォレットアドレス、署名済みトランザクション、ブロックチェーンサービスに必要なリクエストは、通常のウォレット操作の一部として端末外へ送信される場合があります。秘密鍵自体はローカルに保存され、RPCサービスへ送信される署名済みトランザクションには含まれません。

> <mark style="color:green;">**秘密鍵はユーザー自身の管理下で端末内に保持されます。KEYRING PROは秘密鍵を預かることなく、ウォレット操作を承認するためにローカルで使用します。**</mark>
>
> <mark style="color:green;">**これにより、ウォレットアカウントと資産へのアクセスを管理できるのはユーザー自身だけです。**</mark>

KEYRING PROは秘密鍵の復旧用コピーをサーバーに保持していないため、KEYRINGチームがアカウントへアクセスしたり、トランザクションを承認したり、紛失した秘密鍵を復旧したりすることはできません。

ユーザーは、秘密鍵とバックアップファイルを安全に保管する必要があります。両方へアクセスできなくなった場合、ウォレットアカウントへ永久にアクセスできなくなる可能性があります。

## 追加のセキュリティ機能

### ウォレットの自動ロック

KEYRING PROは、アプリケーションが選択された自動ロック時間を超えてバックグラウンドにある場合、ウォレットを自動的にロックできます。

```js
const elapsedMs = Date.now() - enteredAt
const thresholdMs = Math.max(0, minutes) * 60 * 1000

if (elapsedMs >= thresholdMs) {
  clearVault()
  requestUnlock()
}
```

選択した時間が経過すると、KEYRING PROは有効な保管領域へのアクセスを消去し、アプリケーションをロック解除処理へ戻します。

> <mark style="color:green;">**アプリケーションや端末から離れた場合でも、ウォレットが継続してロック解除された状態になることはありません。選択した自動ロック時間の経過後は、再度認証が必要になります。**</mark>
>
> <mark style="color:green;">**これにより、端末を放置した場合の不正アクセスを防止します。**</mark>

### パスワードの連続試行に対する保護

KEYRING PROは、誤ったパスワードの連続入力を制限します。

```js
export const MAX_FAILED_ATTEMPTS = 5
export const LOCK_DURATION_MS = 60 * 60 * 1000 // 1 hour
```

5回連続でパスワードを間違えると、ウォレットは1時間ロックされます。

失敗回数は、暗号化されたセキュアストレージに保存されます。

```js
const failedAttempts = current.failedAttempts + 1
storeDataToSecureStorage(KEYSTORE.LOCKOUT_FAILED_ATTEMPTS, failedAttempts)
```

最大失敗回数に達すると、KEYRING PROはロックが解除される時刻を保存します。

```js
if (failedAttempts >= MAX_FAILED_ATTEMPTS) {
  const lockUntil = Date.now() + LOCK_DURATION_MS
  storeDataToSecureStorage(KEYSTORE.LOCKOUT_UNTIL, lockUntil)
  return buildState(failedAttempts, lockUntil)
}
```

失敗回数とロック期間は暗号化されたセキュアストレージに保存されるため、アプリケーションを再起動しても制限がすぐに解除されることはありません。

これにより、通常のアプリケーション画面を通じたパスワードの連続推測を中断します。

> <mark style="color:green;">**端末へアクセスできる第三者でも、アプリケーション上で無制限にパスワードを試すことはできません。失敗が繰り返されると、それ以上の試行は一時的に停止されます。**</mark>
>
> <mark style="color:green;">**これにより、パスワードを繰り返し推測する攻撃がより困難になります。**</mark>

この保護機能は、強力なパスワードを使用する必要性に代わるものではありません。

### 暗号化されたバックアップファイル

KEYRING PROのバックアップには、複数のアカウントとウォレット設定が含まれる場合があります。バックアップファイルが保存される前に、ウォレットのデータ全体が暗号化されます。

新しいランダムなsaltが生成され、バックアップパスワードから暗号化キーを導出するために使用されます。

```js
const salt = randomBytes(SALT_LENGTH)
const key = await derivePbkdf2(password, salt, PBKDF2_ITERATIONS_DEFAULT)
```

その後、ウォレットデータはAES-256-GCMで暗号化されます。

```js
const { iv, tag, ciphertext } = encryptAesGcm(JSON.stringify(payload), key)
```

バックアップファイルを作成するたびに、KEYRING PROは次の処理を行います。

* 新しいランダムなsaltを生成します。
* PBKDF2-SHA512でバックアップパスワードを処理します。
* そのバックアップ専用の暗号化キーを作成します。
* AES-256-GCMでウォレットデータを暗号化します。
* 復元に必要な情報とともに暗号化されたデータを保存します。

バックアップを作成するたびに新しいランダムなsaltが生成されるため、各バックアップファイルには、それぞれ固有のパスワードベースの暗号化関係があります。

> <mark style="color:green;">**バックアップファイルを所持しているだけでは、ウォレットを復元できません。正しいバックアップファイルと、そのファイルに設定したパスワードの両方が必要です。**</mark>
>
> <mark style="color:green;">**これにより、バックアップファイルのコピーだけを使用してウォレットを復元されることを防ぎます。**</mark>

誤ったパスワードを入力すると、正しい暗号化キーは生成されません。暗号化データが変更、破損、または損傷している場合も、AES-GCMの認証チェックに失敗します。

新しいバックアップファイルは、必ずパスワードで保護する必要があります。ユーザーは、バックアップファイルとそのパスワードの両方を安全に保管してください。

### 生体認証と端末パスコードによる保護

生体認証によるロック解除を有効にすると、KEYRING PROはOSのキーチェーンを通じて、ウォレットパスワードの保護されたコピーを保存します。

```js
const saved = await Keychain.setInternetCredentials(
  VAULT_USER_PASSWORD,
  VAULT_USER_PASSWORD_ACCOUNT,
  wrapped,
  { accessControl: Keychain.ACCESS_CONTROL.BIOMETRY_ANY_OR_DEVICE_PASSCODE }
)
```

端末によって、認証には次の方法が使用される場合があります。

* Face ID
* Touch ID
* 指紋認証
* 端末のパスコード

保護された認証情報を保存した後、KEYRING PROはOSの認証画面を通じて、保存した情報を直ちに読み取ろうとします。認証に失敗した場合、キャンセルされた場合、または保存した値を確認できない場合、そのエントリは削除されます。

生体認証によるロック解除は、アプリケーション内に表示されるだけの確認ではありません。保護されたウォレット認証情報へのアクセスは、iOSまたはAndroidが提供するセキュリティ機能によって制御されます。

> <mark style="color:green;">**生体認証によって秘密鍵が直接表示されることはありません。保護されたウォレットパスワードへのアクセスを許可し、そのパスワードを使用して暗号化された秘密鍵保管領域をロック解除します。**</mark>
>
> <mark style="color:green;">**これにより、ウォレットをロック解除する前に端末レベルの保護が追加されます。**</mark>

## 検証可能なKEYRING PROの機能

オープンソースは、セキュリティ設定を公開するだけではありません。KEYRING PROの主要なウォレット機能がどのように実装されているかも確認できます。

### アカウントの作成とインポート

KEYRING PROは、次の方法に対応しています。

* 自動生成された秘密鍵
* 手動で入力された秘密鍵
* 他の互換性のあるウォレットからインポートされた秘密鍵

コードは秘密鍵をEVMアカウントへ変換し、対応するウォレットアドレスを導出します。

```js
export const generateEvmAccountFromPrivateKeyEvm = (privateKey, isFromKeyCard = false, addressProps) => {
  try {
    const wallet = privateKeyToAccount(add0xToPrivateKey(privateKey))
    return { chain: STANDARD_CHAIN.Evm, address: addressProps || lowerCase(wallet.address), privateKey: isFromKeyCard ? '' : remove0xFromPrivateKey(privateKey) }
  } catch (error) {
    return null
  }
}
```

無効な秘密鍵の場合、アカウントは返されません。KEYRING PROはアカウントを追加する前に、同じウォレットアドレスがすでに存在しないかも確認し、その後、秘密鍵を専用ストレージへ移動します。

> <mark style="color:green;">**新しいアカウントを作成する場合でも、既存のアカウントをインポートする場合でも、KEYRING PROは同じアカウント検証処理と秘密鍵保存処理を適用します。**</mark>
>
> <mark style="color:green;">**これにより、新規作成されたアカウントとインポートされたアカウントの両方に、一貫した保護が適用されます。**</mark>

### ホットアカウント、NFC KeyCardアカウント、閲覧専用アカウント

KEYRING PROは、3種類のアカウントに対応しています。

* **ホットアカウント：** 秘密鍵が端末上で生成またはインポートされます。
* **NFC KeyCardアカウント：** 暗号化された秘密鍵データが対応するNFCカードへ保存されます。
* **閲覧専用アカウント：** 公開ウォレットアドレスのみが登録されます。

閲覧専用アカウントでは、秘密鍵をインポートまたは保存することなく、アカウント情報が作成されます。

```js
const accountData = {
  chain: STANDARD_CHAIN.Evm,
  address: addressLower,
  name: accountName,
  status: true,
  accountType: ACCOUNT_TYPE.VIEW_ONLY
}
```

閲覧専用アカウントには保存すべき秘密鍵が存在しないため、閲覧専用機能は秘密鍵ストレージへアクセスしません。

閲覧専用アカウントでは、残高やアクティビティを確認できますが、KEYRING PROが秘密鍵を保持していないため、トランザクションへ署名することはできません。

> <mark style="color:green;">**閲覧専用アカウントでは、秘密鍵をインポートまたは保存することなく、ウォレットアドレスを確認できます。**</mark>
>
> <mark style="color:green;">**これにより、そのアカウントを管理する秘密鍵を公開することなく、アカウントを監視できます**</mark>**。**

NFC KeyCardアカウントの場合、KEYRING PROは通常のアカウントオブジェクトに秘密鍵を保持しません。

```js
return { chain: STANDARD_CHAIN.Evm, address: addressProps || lowerCase(wallet.address), privateKey: isFromKeyCard ? '' : remove0xFromPrivateKey(privateKey) }
```

このアカウントは、コールドアカウントとして個別に識別されます。

```js
accountType: isFromKeyCard ? ACCOUNT_TYPE.COLD : ACCOUNT_TYPE.HOT
```

NFC KeyCardアカウントでは、KEYRING PROはPBKDF2とAES-256-GCMを使用してカードデータを暗号化します。カードを読み取る際には、カードデータに保存されているアドレスが、ウォレットで選択されているアカウントと一致するかも確認します。一致しない場合、秘密鍵は拒否されます。

> <mark style="color:green;">**NFC KeyCardに保存される秘密鍵データは、パスワードベースの暗号化によって保護されます。また、KEYRING PROは秘密鍵を使用する前に、カードのアドレスが選択されたウォレットアカウントと一致することを確認します。**</mark>
>
> <mark style="color:green;">**これにより、NFC KeyCardの不正使用を防ぎ、誤ったアカウントで使用されることを防止します。**</mark>

### 複数のEVMネットワークへの対応

KEYRING PROには、EthereumおよびEVM互換ネットワーク20種類の設定が標準で含まれています。

```js
export const LIST_DEFAULT_CHAIN_ID = [1, 10, 56, 8453, 42161, 43114, 137, 130, 9745, 999, 988, 5000, 42220, 4326, 100, 747474, 143, 57073, 4217, 4663]
```

この設定には、次の情報が含まれています。

* チェーンID
* ネットワーク名
* ネイティブ通貨
* RPC接続
* ブロックエクスプローラー
* トランザクションおよびトークンリンク

リポジトリでは、標準ネットワークとして次のネットワークが定義されています。

Ethereum、Optimism、BNB Chain、Base、Arbitrum、Avalanche、Polygon、Unichain、Plasma、HyperEVM、Stable、Mantle、Celo、MegaETH、Gnosis、Katana、Monad、Ink、Tempo、Robinhood

その他の互換性のあるEVMネットワークも追加できます。

> <mark style="color:green;">**対応するEthereumおよびEVM互換ネットワークで、同じウォレットアカウントを使用できます。ネットワークごとに別のウォレットをインストールする必要はありません。**</mark>
>
> <mark style="color:green;">**これにより、複数のEVMネットワーク上の資産を1つのウォレットで管理できます。**</mark>

### WalletConnect接続

KEYRING PROはWalletConnect v2を使用して、選択したウォレットアカウントを対応するWeb3アプリケーションへ接続します。

承認前に、KEYRING PROは選択したアカウント、承認されたネットワーク、要求されたメソッド、要求されたイベントを使用してセッションを準備します。

```js
const namespacesParams = {
  proposal: proposal.params,
  supportedNamespaces: {
    eip155: { chains: chainsArr, accounts: accountArr, methods, events }
  }
}
```

その後、承認済みの名前空間が作成されます。

```js
const approvedNamespaces = buildApprovedNamespaces(namespacesParams)
```

その名前空間を使用してWalletConnectセッションが承認されます。

```js
const session = await connectorV2.approveSession({
  id: proposal.id,
  namespaces: approvedNamespaces
})
```

承認前に、KEYRING PROは次の情報を使用してセッションを準備します。

* ユーザーが選択したアカウント
* 承認されたEVMネットワーク
* dAppが要求するメソッド
* dAppが要求するイベント

セッションは、選択されたアカウントアドレスへ関連付けられます。利用可能なアカウントがない場合や、要求されたネットワークに対応できない場合には、接続を拒否する処理も含まれています。

> <mark style="color:green;">**KEYRING PROに保存されているすべてのアカウントが自動的に共有されるのではなく、接続するアカウントを自分で選択できます。**</mark>
>
> <mark style="color:green;">**これにより、Web3アプリケーションと共有するアカウントやネットワークを、より細かく管理できます。**</mark>

WalletConnect接続は、dAppの安全性を保証するものではありません。接続リクエスト、メッセージ、トランザクションを承認する前に、必ず内容を確認してください。

### トークンスワップとクロスチェーンブリッジ

KEYRING PROは、スワップおよびブリッジプロバイダーに共通のサービス構造を使用します。

```js
switch (providerName) {
  case 'debridge':
    return new DebridgeAdapter(config)
  case 'relay':
    return new RelayAdapter(config)

  default:
    return new DebridgeAdapter(config)
}
```

公開ソースには、RelayとdeBridgeのサービスアダプターが含まれています。

サービス構造は、次の処理を行います。

* プロバイダーの選択
* 見積もりの取得
* トークン承認状態の確認
* トランザクションの準備
* スワップまたはブリッジの実行
* トランザクション進行状況の追跡

> <mark style="color:green;">**対応する同一チェーン内のスワップやクロスチェーン転送を、プロバイダーごとに別のアプリケーションを使用することなく、統一されたウォレット画面から実行できます。**</mark>
>
> <mark style="color:green;">**これにより、対応ネットワーク間のスワップや資産移動を、より便利に行えます。**</mark>

### 内蔵AIアシスタント

公開リポジトリには、ウォレットアカウントとネットワークを選択できる専用のAIアシスタント画面が含まれています。

このアシスタントは、ユーザーがウォレット情報を理解し、対応するウォレット操作を準備できるよう支援するために設計されています。リポジトリでは、ユーザーの承認を前提としたトークン送信や対応する流動性操作の準備などが例として説明されています。

機密性の高い操作では、引き続きウォレットの通常の確認、承認、トランザクション署名処理に従う必要があります。

> <mark style="color:green;">**AIアシスタントはウォレット操作の説明や準備を支援できますが、最終的な操作内容を確認して承認する責任はユーザーにあります。**</mark>
>
> <mark style="color:green;">**これにより、便利なサポートを提供しながら、すべてのウォレット操作に対する最終的な管理権限はユーザー自身に維持されます。**</mark>

## オープンソースが重要である理由

ウォレットは、秘密鍵を暗号化している、バックアップを保護している、トランザクションをローカルで署名していると説明できます。

オープンソースであれば、専門知識を持つ第三者が、それらの説明が実際の実装に反映されているか確認できます。

KEYRING PROのリポジトリでは、次の内容を確認できます。

* 秘密鍵がどのように生成されるか
* どのライブラリが秘密鍵を生成するか
* どの暗号曲線が使用されるか
* パスワードがどのように暗号化キーへ変換されるか
* どの暗号化アルゴリズムが秘密鍵を保護するか
* 秘密鍵がどこに保存されるか
* 秘密鍵がどのように取得されるか
* ウォレットがロックされた際に何が起きるか
* パスワードの連続試行がどのように制限されるか
* バックアップファイルがどのように暗号化・復元されるか
* 生体認証がどのようにアクセスを制御するか
* ブロードキャスト前にトランザクションが署名されるか
* RPCリクエストに秘密鍵が含まれているか
* ホットアカウント、NFC KeyCardアカウント、閲覧専用アカウントがどのように機能するか
* WalletConnectセッションがどのように承認されるか
* ネットワーク、スワップ、ブリッジ、その他の機能がどのように実装されているか

これは、「秘密鍵は暗号化されています」という一般的な説明だけよりも、高い信頼性を提供します。確認者は、その説明を支える実際のメソッド、ライブラリ、セキュリティ設定、保存処理を確認できます。

開発者は、アプリケーションをビルドし、その設計を学び、改善を提案し、適用されるオープンソースライセンスに従って新しいウォレットソフトウェアを作成することもできます。

> <mark style="color:pink;">**オープンソースとは、すべてのユーザーがコードの各行を理解しなければならないという意味ではありません。実装を公開し、第三者が独立して確認できるようにすることが目的です。**</mark>

## 透明性によるセキュリティ

KEYRING PROは、すべてのユーザーが暗号技術のソースコードを理解することを求めていません。

代わりに、開発者、監査担当者、セキュリティ専門家、組織が、秘密鍵、パスワード、バックアップ、ウォレットアクセス、トランザクションがどのように保護されているかを確認できるよう、コードを公開しています。

セルフカストディ型ウォレットにおいて、ユーザーがセキュリティ上の主張を盲目的に信頼する必要があってはなりません。

> <mark style="color:pink;">**ユーザーの資産を保護するソフトウェアは、第三者が独立して検証できるものであるべきです。**</mark>

## オープンソースによる独立したウォレット開発

KEYRING PROはオープンソースであるため、開発者はGPL-3.0ライセンスに従って、コードを学習、変更、ビルドし、動作するウォレットを作成したり、別のウォレットプロジェクトの基盤として使用したりできます。

これはオープンソースの目的の一つです。開発者は実装から学び、透明性のあるコードを基に新しいウォレットソリューションを作成できます。

ただし、KEYRING PROのソースコードから作成されたウォレットが、自動的にKEYRING PROの公式製品になるわけではありません。

第三者の開発者は、次のような変更を行う可能性があります。

* 秘密鍵の保護システムを変更する
* 異なるサービスへウォレットを接続する
* セキュリティ機能を追加または削除する
* ウォレットデータの取り扱い方法を変更する
* 異なる名称でアプリケーションを配布する
* KEYRING PROに似た外観でありながら、異なる動作をするアプリケーションを作成する

そのため、ユーザーは次の操作を行う前に、必ずKEYRINGの公式チャネルからKEYRING PROをダウンロードし、正しい開発者が公開しているアプリケーションであることを確認してください。

* ウォレットを作成する
* パスワードを入力する
* 秘密鍵をインポートする
* NFC KeyCardをスキャンする
* バックアップファイルを復元する
* トランザクションを承認する

オープンソースによってコードはすべての人に公開されますが、Bacoorが開発、配布、保守、サポートしているのは、公式のKEYRING PROアプリケーションのみです。

Bacoorは、独立した第三者が行った変更を確認または管理することはできません。そのため、非公式フォーク、改変されたビルド、複製アプリケーション、KEYRING PROを装うアプリケーションについて、Bacoorが検証、サポート、または責任を負うことはできません。

> <mark style="color:pink;">**機密性の高いウォレット情報を入力する前に、必ず公式のKEYRING PRO Walletを使用していることを確認してください。**</mark>
