Skip to content

블록체인 통합

SirrChat의 블록체인 통합은 EVM 지갑 서명을 사용한 비밀번호 없는 인증을 가능하게 합니다. 이 혁신적인 접근 방식은 기존 비밀번호 취약점을 제거하는 동시에 암호학적으로 안전한 액세스 제어를 제공합니다.

개요

블록체인 인증 모듈(auth.pass_blockchain)을 사용하면 사용자가 기존 비밀번호 대신 이더리움(또는 EVM 호환) 지갑 서명을 사용하여 인증할 수 있습니다.

작동 방식

  1. 사용자 등록: 사용자의 지갑 주소가 이메일 계정에 등록됩니다
  2. 인증 요청: 클라이언트가 개인 키로 챌린지 메시지에 서명합니다
  3. 서명 확인: 서버가 서명에서 공개 키를 복구합니다
  4. 액세스 부여: 복구된 주소가 등록된 주소와 일치하면 액세스가 부여됩니다

구성

기본 설정

sirrchatd.conf에 블록체인 인증 추가:

conf
# 블록체인 구성
blockchain sirrchatd {
    rpc_endpoint https://mainnet.infura.io/v3/YOUR_PROJECT_ID
    chain_id 1  # Ethereum Mainnet
}

# 인증 모듈
auth.pass_blockchain blockchain_auth {
    blockchain &sirrchatd
    storage &local_mailboxes
}

# IMAP 엔드포인트에서 사용
imap tls://0.0.0.0:993 {
    auth &blockchain_auth
    storage &local_mailboxes
}

지원되는 체인

SirrChat은 모든 EVM 호환 블록체인을 지원합니다:

체인Chain ID네트워크
Ethereum Mainnet1프로덕션
Ethereum Goerli5테스트넷
Ethereum Sepolia11155111테스트넷
BSC Mainnet56프로덕션
BSC Testnet97테스트넷
Polygon Mainnet137프로덕션
Polygon Mumbai80001테스트넷
Arbitrum One42161프로덕션
Optimism10프로덕션

인증 흐름

1. 챌린지 생성

사용자가 인증을 시도할 때 서버는 챌린지 메시지를 생성합니다:

Challenge: <random_nonce>
Timestamp: <unix_timestamp>
Service: sirrchat

2. 클라이언트 측 서명

클라이언트가 이더리움 지갑을 사용하여 챌린지에 서명합니다:

javascript
// ethers.js 사용 예제
const message = `Challenge: ${nonce}\nTimestamp: ${timestamp}\nService: sirrchat`;
const signature = await wallet.signMessage(message);

3. 서버 측 확인

서버가 서명을 확인하고 주소를 복구합니다:

go
// 내부 확인 프로세스
func (bc *Ethereum) CheckSign(ctx context.Context, pk, sign, message string) (bool, error) {
    hash := crypto.Keccak256Hash([]byte(message))
    signature := hexutil.MustDecode(sign)

    // Recover public key from signature
    pubKey, err := crypto.SigToPub(hash.Bytes(), signature)
    if err != nil {
        return false, err
    }

    // Get address from public key
    recoveredAddr := crypto.PubkeyToAddress(*pubKey)

    // Compare with registered address
    return recoveredAddr.Hex() == pk, nil
}

사용자 관리

블록체인 사용자 등록

bash
# 이메일 계정에 지갑 주소 등록
sirrchatd creds create-blockchain \
    --email [email protected] \
    --address 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb

# 블록체인 사용자 목록
sirrchatd creds list-blockchain

지갑 주소 업데이트

bash
# 기존 계정의 지갑 주소 업데이트
sirrchatd creds update-blockchain \
    --email [email protected] \
    --address 0xNewAddress

블록체인 인증 제거

bash
# 블록체인 인증 제거 (이메일 계정은 유지)
sirrchatd creds remove-blockchain --email [email protected]

클라이언트 구현

이메일 클라이언트 구성

블록체인 인증을 사용하도록 이메일 클라이언트 구성:

IMAP 설정:

  • 서버: your-domain.com
  • 포트: 993
  • 보안: SSL/TLS
  • 사용자 이름: [email protected]
  • 비밀번호: <signature> (지갑 서명)

커스텀 클라이언트 예제

커스텀 클라이언트에서 블록체인 인증을 구현하는 간단한 예제:

javascript
const ethers = require('ethers');

class BlockchainEmailAuth {
    constructor(walletAddress, privateKey) {
        this.wallet = new ethers.Wallet(privateKey);
        this.address = walletAddress;
    }

    async generateAuthCredentials(challenge, timestamp) {
        const message = `Challenge: ${challenge}\nTimestamp: ${timestamp}\nService: sirrchat`;
        const signature = await this.wallet.signMessage(message);

        return {
            username: `[email protected]`,
            password: signature,
            address: this.address
        };
    }

    async connectIMAP(host, port) {
        // Get challenge from server
        const { challenge, timestamp } = await this.getChallengeFromServer();

        // Generate credentials
        const creds = await this.generateAuthCredentials(challenge, timestamp);

        // Connect to IMAP server
        // ... use creds to authenticate
    }
}

보안 고려 사항

모범 사례

  1. 개인 키를 공유하지 마세요: 개인 키는 절대로 전송하거나 서버에 저장해서는 안 됩니다
  2. 하드웨어 지갑 사용: 프로덕션 사용 시 하드웨어 지갑 통합 고려
  3. 논스 만료 구현: 챌린지 논스는 짧은 기간 후 만료되어야 합니다
  4. 속도 제한: 인증 시도에 대한 속도 제한 구현
  5. 감사 로깅: 보안 모니터링을 위해 모든 인증 시도 기록

재생 공격 방지

서버는 재생 공격 방지 기능을 포함합니다:

conf
auth.pass_blockchain blockchain_auth {
    blockchain &sirrchatd
    storage &local_mailboxes

    # 챌린지 구성
    challenge_expiry 300s  # 5분
    nonce_cache_size 10000
}

기존 인증 대비 장점

보안 이점

  • 비밀번호 저장 없음: 비밀번호 데이터베이스 침해 제거
  • 암호학적 확인: 검증된 타원 곡선 암호화 기반
  • 비밀번호 재사용 없음: 각 서명이 고유함
  • 피싱 방지: 자격 증명을 공개하도록 속일 수 없음

사용자 경험

  • 비밀번호 관리 불필요: 사용자가 비밀번호를 기억할 필요 없음
  • 멀티 디바이스: 모든 디바이스에서 동일한 지갑 사용 가능
  • 복구 옵션: 비밀번호 재설정 대신 지갑 복구 메커니즘 사용

Web3 애플리케이션과의 통합

DApp 통합

DApp에 이메일 기능 통합:

javascript
// 예제: DApp에서 이메일 전송
async function sendEmailFromDApp(web3Provider) {
    const signer = web3Provider.getSigner();
    const address = await signer.getAddress();

    // Get challenge
    const challenge = await fetchChallenge();

    // Sign challenge
    const signature = await signer.signMessage(challenge.message);

    // Authenticate and send email
    await sendEmail({
        from: `${address}@yourdomain.com`,
        signature: signature,
        to: '[email protected]',
        subject: 'Hello from DApp',
        body: 'This email was sent using blockchain authentication!'
    });
}

문제 해결

일반적인 문제

서명 확인 실패

bash
# 주소가 등록되었는지 확인
sirrchatd creds list-blockchain | grep [email protected]

# 챌린지 형식 확인
# 클라이언트와 서버가 동일한 메시지 형식을 사용하는지 확인

RPC 연결 문제

bash
# RPC 엔드포인트 테스트
curl -X POST https://mainnet.infura.io/v3/YOUR_PROJECT_ID \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'

고급 구성

다중 체인 지원

conf
# 여러 체인 지원
blockchain eth_mainnet {
    rpc_endpoint https://mainnet.infura.io/v3/YOUR_PROJECT_ID
    chain_id 1
}

blockchain bsc_mainnet {
    rpc_endpoint https://bsc-dataseed1.binance.org
    chain_id 56
}

auth.pass_blockchain multi_chain_auth {
    blockchain &eth_mainnet &bsc_mainnet
    storage &local_mailboxes
}

커스텀 확인 로직

커스텀 확인을 위해 블록체인 모듈 확장:

go
// 커스텀 확인 구현
type CustomBlockchainAuth struct {
    baseAuth *blockchain.Ethereum
}

func (c *CustomBlockchainAuth) VerifyWithNFT(ctx context.Context, address, signature string) (bool, error) {
    // Verify signature
    valid, err := c.baseAuth.CheckSign(ctx, address, signature, message)
    if err != nil || !valid {
        return false, err
    }

    // Additional NFT ownership check
    hasNFT, err := c.checkNFTOwnership(ctx, address)
    return hasNFT, err
}

API 참조

핵심 인터페이스

go
type BlockChain interface {
    // Send raw transaction to blockchain
    SendRawTx(ctx context.Context, rawTx string) error

    // Get blockchain type
    ChainType(ctx context.Context) string

    // Verify signature and check if it matches public key
    CheckSign(ctx context.Context, pk, sign, message string) (bool, error)
}

리소스


블록체인 인증은 암호학적 확인을 통해 보안을 강화하면서 비밀번호를 제거합니다.

Released under the GPL 3.0 License.