Ynotbit은 notbit을 기반으로 만든 간결한 데스크톱 Bitmessage 클라이언트다. 제작자는 0.7.0 버전을 Linux, macOS, Windows용 사전 빌드 파일로 배포하며, MIT 라이선스를 적용한다.

Ynotbit은 비밀번호로 보호하는 보관소(vault)에 신원 키를, 별도의 암호화된 메일함 문서에 서신을 저장한다. 키가 필요 없는 릴레이는 보관소가 잠겨 있는 동안에도 네트워크 객체를 계속 수집한다. 보관소를 열면 저장해 둔 객체를 검사해 일치하는 편지를 메일함에 저장한다.

내려받기와 시작하기

0.7.0 릴리스 페이지에서 Linux(x86_64), macOS(Apple Silicon), Windows(x86_64)용 사전 빌드 파일을 내려받을 수 있다. 제작자는 이 빌드가 CI 테스트를 거쳤다고 설명한다. 각 빌드의 보장 범위와 한계는 아래의 현재 한계를 참조하면 된다.

macOS 앱은 임시 서명만 되어 있고 공증은 받지 않았다. 따라서 macOS가 내려받은 파일을 격리한다. ynotbit.app을 /Applications로 옮긴 뒤 다음 명령으로 격리를 한 번 해제해야 한다.

sh
sudo xattr -cr /Applications/ynotbit.app

앱을 처음 사용할 때는 .bmvault 파일을 만들거나 연다. File → Create vault… 또는 잠금 화면의 Create vault를 선택하면 보관소와 첫 신원을 함께 만드는 대화상자가 열린다. 무작위 키를 쓰거나 비밀 문구에서 키를 만들 수 있으며, 더 짧은 주소를 찾는 옵션도 있다. Identity → Create identity…에서도 같은 대화상자를 사용할 수 있다. keys.dat를 가져오거나 공유 문구와 예상 주소를 사용해 chan에 참여할 수도 있다.

그다음 Documents 또는 쓰기 권한이 있는 다른 폴더에 .bmmail 문서를 만들거나 연다. 편지를 쓰려면 Write a letter를 선택하고 발신 신원을 고른 뒤 받는 사람을 지정한다. 받는 사람 칸에 연락처 이름이나 BM 주소를 입력하거나 To 옆의 연락처 버튼을 쓸 수 있다. 변경 사항은 암호화된 메일함에 자동 저장된다. Send를 누르면 전송이 시작되며, 기존 초안에는 Edit / Send 컨트롤이 표시된다.

전송 진행 상황은 보낼 편지함(Outbox)에서 확인한다. 키 조회와 작업 증명(proof of work)에 시간이 걸릴 수 있다. 받는 사람의 확인 응답은 비동기적으로 도착하며, 읽음 확인을 뜻하지 않는다. 사용을 마치면 보관소를 잠근다. 메시지 준비는 일시 중지되고 메일함은 닫히지만, 릴레이는 이미 제출한 암호화된 네트워크 객체를 계속 처리한다.

편지에서 주소 옆의 사람 추가 버튼을 누르거나 Contacts → Add contact…를 선택하면 연락처 이름을 붙일 수 있다. 이름은 메시지 목록, 편지 보기, 작성 화면에서 전체 주소와 함께 표시된다.

대화하려면 왼쪽 메뉴에서 Chats를 열고 New chat을 선택한다. 연락처 이름이나 BM 주소를 입력하고, 여러 신원을 보유했다면 대화에 사용할 신원을 고른다. 메시지는 Markdown 형식이며 Enter는 전송, Shift+Enter는 줄 바꿈이다. 대화는 특정 신원에 연결되므로 같은 상대라도 서로 다른 신원으로 대화하면 별도 대화로 표시된다. 메시지 아래의 체크 표시는 전송 상태를 나타낸다. 대기 중, 네트워크 전송, 전달됨 순이며, 전달됨은 받는 사람의 확인 응답이지 읽음 확인은 아니다. 대화 메시지는 네트워크에 24시간 보관된다. 그때까지 전달되지 않은 메시지는 만료로 표시된다. 대화는 받은 편지함에는 나타나지 않지만 메일함과 백업에는 남는다.

발신자의 브로드캐스트를 받아보려면 Subscriptions에서 + Subscribe…를 선택하거나 Identity → Subscribe to broadcasts…를 이용한다. 해당 발신자의 게시물이 피드에 표시된다. 새 메일함은 Bitmessage 다이제스트와 ynotbit 자체 업데이트 알림을 기본 구독한다. 편지 작성 화면의 + 버튼, 마우스 오른쪽 버튼 메뉴, 또는 이미지 파일 끌어 놓기를 이용해 편지에 그림을 넣을 수 있다.

File → Back up mailbox and vault는 두 문서를 모두 백업한다. 메일함만으로는 암호화 키를 복구할 수 없으므로 둘 다 보관해야 한다. 비밀번호를 바꿔도 이전 보관소 복사본이나 백업이 무효화되지는 않는다. 가져오기 과정에서도 원본의 평문 keys.dat는 그대로 유지된다.

기능과 메시지 전달

Ynotbit은 Argon2id(64 MiB, 3회 반복)와 XChaCha20-Poly1305를 사용하는 이동 가능한 보관소를 제공한다. 키 메모리 할당을 보호하고, 비밀번호 변경과 신원 이름 지정, 결정론적 v3/v4 chan을 지원한다. 한 대화상자에서 보관소와 첫 신원을 만들 수 있으며, 무작위 키 또는 PyBitmessage의 키 파생 방식에 따라 비밀 문구에서 만든 키를 사용할 수 있다. 더 짧은 주소를 찾는 옵션도 제공한다.

SQLCipher 기반 메일함은 초안, 메시지 본문, 주소, 공개 키, 전달 기록, 확인 토큰, 구독, 체크포인트를 암호화해 보관한다. 기존 v1 메일함 문서는 초안을 잃지 않는 트랜잭션 방식으로 마이그레이션한다.

받는 사람의 공개 키를 이용한 전송, v2/v3/v4 공개 키 조회와 응답, 백그라운드 작업 증명을 지원한다. 작업 증명은 CPU 코어 하나를 제외한 나머지 코어와 GPU에서 실행한다. macOS에서는 Metal, 그 밖의 플랫폼에서는 OpenCL을 사용한다. 보낼 편지함과 전달 기록은 유지된다.

개인 메시지의 복호화와 발신자 확인, 확인 응답, 제한된 자동 만료 재시도, 수동 재시도와 취소, 인증된 발신자 키를 사용한 답장을 지원한다. 이미 릴레이된 객체는 취소해도 회수할 수 없다.

주소록에는 암호화된 메일함에 저장되는 비공개 연락처 이름이 포함된다. 이름은 외부로 전송되지 않는다. 편지에서 한 번 눌러 연락처를 추가할 수 있으며, 메시지 목록과 편지 보기 및 작성 화면에 이름이 나타난다. 작성 화면에서는 이름 자동 완성과 연락처 선택기를 사용할 수 있고, 이름 옆에는 항상 전체 주소가 표시된다.

채널 이름은 #<name> 형식을 사용한다. 공개 채널의 이름은 공유 문구이며, 예를 들어 bitmessage 채널은 #bitmessage로 표시된다. 비밀 채널은 사용자가 정한 이름을 쓰고 문구 입력란은 숨겨진다. 보관소를 열 때 기존 [chan] <phrase> 이름은 #<phrase>로 바뀐다. 채널에는 이름을 표시하는 선택기, 별도의 메시지 목록과 검색, Write to channel 기능이 있다. 채널 목록은 읽지 않은 메시지 점이 표시된 식별자 아이콘 열로 접을 수 있다. BM 주소는 고정 폭 글꼴로 표시되며, 주소마다 GitHub 스타일 식별자 아이콘이 붙는다.

편지 보기 화면은 개인 편지, chan 개인 메시지, 익명 chan 게시물, 브로드캐스트 등 유형별로 편지를 구분한다. 일반 텍스트, 텍스트, Markdown, 16진수 보기를 제공하며 Markdown과 읽을 수 없는 바이너리 형식을 자동 감지한다. 제목, 세부 정보, 본문은 하나의 영역에서 함께 스크롤된다. 메시지 세부 정보에는 발신자와 수신자 주소가 정렬되어 표시되고, 성공한 확인 응답은 색으로 구분된다. 전달 기록에는 준비, 키 확인, 피어 전송, 확인 응답, 메일함 수신 단계가 나타난다.

브로드캐스트 게시(v4/v5 객체)와 구독 기능도 제공한다. 구독한 발신자는 채널 목록과 비슷한 왼쪽 메뉴에 표시되며, 각 발신자의 게시물은 카드 피드로 나타난다. 카드에서 비공개 답장, 전달, 텍스트 복사, 별도 창 열기, 보관, 휴지통 이동을 할 수 있다. 새 메일함은 Bitmessage 다이제스트를 구독한다. 공유 chan, 백그라운드 폴더 검색, 읽음 상태, 보관, 휴지통 이동과 복원, 영구 삭제도 지원한다.

대화 기능은 기본 창의 별도 페이지에서 일대일 대화를 제공한다. 대화 목록에는 상대의 사진과 이름, 최신 메시지와 시간, 보낸 메시지의 전달 체크 표시, 읽지 않은 메시지 수가 나타나며 Chats 버튼에는 알림 점이 표시된다. 대화 화면은 Markdown 메시지를 말풍선으로 보여주고 시간과 전달 상태를 표시한다. 각 대화는 사용자 신원 하나와 상대 한 명 사이에 연결되며 해당 신원을 유지한다. Enter는 전송, Shift+Enter는 줄 바꿈이다. 링크는 먼저 확인을 요청하며 https만 연다. 대화 메시지는 제목이 비어 있고 작은 JSON 본문을 담은 일반 Bitmessage 메시지다. 네트워크에는 24시간 보관되며, 편지와 같은 작업 증명, 게시, 확인 응답 절차를 사용한다. 받은 편지함에는 나타나지 않으며 네트워크에서 사라진 뒤에도 메일함과 백업에 남는다.

업데이트 알림은 ynotbit 릴리스 주소(BM-2666hf5eAbjCJMaPwC7eG3Um55QJGM)에서 서명한 브로드캐스트로 제공된다. 구독하지 않아도 새 버전이 나오면 배너가 표시된다. Settings → Notifications에서 알림을 끌 수 있다.

별도의 notbit 릴레이는 Linux, macOS, Windows에서 작동하며 보관소나 메일함 키를 받지 않는다. 피어에게 /ynotbit:<version>/으로 자신을 식별한다. 크기가 제한된 로컬 큐는 네트워크 객체를 받아 작업 증명을 검증하고, 수락·거부와 연결된 피어에 대한 제공 기록을 남긴다. 수신 상태는 재시작 후에도 유지된다. PyBitmessage와 MiNode처럼 TLS를 제공하는 피어와는 핸드셰이크 뒤 연결을 TLS로 전환한다. PyBitmessage와 같은 방식으로 익명 ECDH를 사용한다. 이 방식은 수동 감시자가 트래픽을 읽지 못하게 하지만 피어의 신원은 인증하지 않는다.

네트워크 객체는 objects.sqlite라는 SQLite 파일 하나에 저장된다. 릴레이가 객체를 기록하고 보존 한도에 따라 정리하며, 앱은 이 파일을 읽는다. 새 객체는 다음 새로 고침 때 메일함으로 들어온다. 데스크톱 인터페이스는 QML이나 Qt Quick 없이 Qt Widgets를 사용한다. 직접 그리는 메시지 목록은 메시지 요약을 최대 100개씩 세 페이지까지 보관하고, 선택한 메시지의 본문만 불러온다.

편지 작성기는 시각적 Markdown 편집기다. 각 문단 옆의 표시(¶, H1–H6, 목록, 코드)를 누르면 MarkText처럼 Turn into 메뉴가 열린다. 답장은 같은 편집기에서 이메일 형식으로 > 인용을 넣는다. 인용한 텍스트는 편집할 수 있지만 인용 형식은 유지되며, 편지 보기 화면은 인용 단계별로 색 막대를 표시한다. 편지를 전달할 수도 있다.

Bitmessage에는 첨부 파일 기능이 없으므로 그림은 표준 Markdown data: URL로 편지 안에 넣고 한 편지에 맞게 크기를 줄인다. 편지 보기 화면은 이 그림과 PyBitmessage의 인라인 그림도 표시한다. PNG, JPEG, GIF, WebP만 불러온다. 렌더링된 메시지는 로컬 파일이나 원격 이미지를 가져오지 않는 안전한 Markdown 문서를 사용한다. 기본 모양은 시스템 색상 설정을 따르며, 밝은 모드와 어두운 모드를 선택할 수도 있다.

인터페이스 언어는 영어, 중국어 간체·번체, 일본어, 한국어, 러시아어, 우크라이나어다. 기본적으로 시스템 언어를 따르며, Settings → Appearance에서 언어를 직접 고를 수 있다. 변경 사항은 재시작 뒤 적용되고 날짜 표시도 선택한 언어를 따른다.

피어 수 표시, 오프라인 모드, 노드 재시작 기능을 제공한다. 기본 창의 설정 페이지는 왼쪽 메뉴의 톱니바퀴 또는 File → Settings…에서 연다. 설정에는 네트워크(추가 피어, SOCKS5 프록시, 수신 연결, 라우터 포트), 저장 공간, 전송, 모양, 알림, 보안 항목이 있다. 네트워크 캐시 보존 기간, 최근 문서 경로, 통합 백업도 설정할 수 있다.

전달 상태는 대기열 등록, 키 요청, 영수증 준비, 작업 증명, 피어 대기, 확인 응답 대기, 확인 완료의 단계로 구분된다. 브로드캐스트와 chan 메시지는 받는 사람의 영수증 없이 게시 완료 상태가 될 수 있다. 피어에게 객체를 제공했다는 사실만으로 모든 피어나 최종 수신자가 받았다고 증명되지는 않는다.

빌드와 테스트

필요한 항목은 CMake 3.22 이상, C++20, Qt 6.8 이상(Core, Gui, Widgets, Network, Test), OpenSSL, libsodium, SQLCipher, pkg-config, Ninja다. Python 3은 로컬 루프백 릴레이 테스트에 사용한다. 고정된 저장소 의존성을 소스에서 빌드하려면 Autoconf, Automake, make, Tcl도 필요하다.

sh
scripts/build-dependencies.sh /absolute/scratch /absolute/deps
export PKG_CONFIG_PATH=/absolute/deps/lib/pkgconfig
cmake -S . -B build -G Ninja \
 -DCMAKE_PREFIX_PATH=/absolute/Qt/6.8.3/macos \
 -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel 4
ctest --test-dir build --output-on-failure

Linux에서는 설치된 Qt의 gcc_64 디렉터리를 사용한다. 실행 파일 대상 이름은 ynotbit이며, macOS에서는 ynotbit.app이 생성된다. 테스트는 임시 문서와 루프백 피어를 사용하고 공개 네트워크 메시지는 사용하지 않는다. 독립적인 와이어 테스트 픽스처는 Python cryptography 50.0.1로 tests/generate_wire_fixtures.py를 실행해 다시 만들 수 있다. 일반 테스트 묶음에는 이 패키지가 필요하지 않다.

Windows에서는 MSVC와 Ninja로 빌드한다. build-dependencies.sh 대신 vcpkg의 vcpkg.json 매니페스트와 x64-windows 트리플릿으로 OpenSSL, libsodium, SQLCipher를 가져오고 -DCMAKE_TOOLCHAIN_FILE=<vcpkg>/scripts/buildsystems/vcpkg.cmake를 전달한다. 세 플랫폼의 CI 검증 빌드 절차는 .github/workflows/release.yml에서 확인할 수 있다.

번역 파일은 translations/ynotbit_<lang>.ts에 있으며 Qt Linguist나 텍스트 편집기로 수정할 수 있다. 코드에서 사용자에게 보이는 문구를 바꾼 뒤 다음 명령으로 번역 파일을 갱신한다. scripts/check-translations.py는 테스트에도 포함되며, 번역되지 않은 항목이나 깨진 %1 자리표시자가 있으면 실패한다. 저장소와 프로토콜 계층의 오류 메시지는 scripts/update-error-catalog.py로 수집한다.

README 스크린샷은 실제 메일함이 아니라 데모 데이터로 만든다. 다음 명령으로 기본 스크린샷을 다시 만들 수 있다.

sh
cmake --build build --target readme_screenshots
QT_QPA_PLATFORM=offscreen build/readme_screenshots docs/images

일본어, 한국어, 중국어 간체·번체, 러시아어, 우크라이나어 데모 편지가 담긴 번역별 스크린샷은 ... docs/images/<lang> <lang> 형식으로 생성한다. <lang>에는 ja, ko, zh_CN, zh_TW, ru, uk를 쓴다.

Qt 런타임 라이브러리를 포함해 재배포용 빌드를 패키징하려면 다음 스크립트를 사용한다.

sh
# macOS
scripts/package-macos.sh /absolute/build /absolute/ynotbit-macos-arm64.zip /absolute/Qt/6.8.3/macos
# Linux — linuxdeploy로 자체 포함 AppImage 하나를 빌드한다
scripts/package-linux.sh /absolute/build /absolute/ynotbit-x86_64.AppImage /absolute/Qt/6.8.3/gcc_64

# Windows
scripts/package-windows.ps1 -BuildDir C:\absolute\build -OutputZip C:\absolute\ynotbit-windows-x86_64.zip `
 -QtBinDir C:\absolute\Qt\6.8.3\msvc2022_64\bin -VcpkgBinDir C:\absolute\build\vcpkg_installed\x64-windows\bin

문서와 네트워크 데이터

보관소와 메일함 문서는 원하는 위치에 둘 수 있다. 노드와 캐시 디렉터리는 Qt의 애플리케이션 데이터 위치를 사용한다. 내부 애플리케이션 식별자는 이전 알파 버전의 캐시와 호환되도록 NotbitDesktop/Notbit Desktop으로 유지한다. --data-dir /absolute/path는 노드 폴더를 지정된 경로로 바꾼다. --portable은 실행 위치를 기준으로 ./notbit-data/node를 사용한다. --offline은 네트워크 연결 없이 시작한다. 앱을 종료하면 릴레이도 중지된다.

릴레이는 포트 8444에서 수신 연결을 받는다. 프록시를 설정하면 수신 연결을 받지 않는다. 릴레이는 UPnP를 통해 라우터에 해당 포트를 열도록 요청하며, Settings → Network에서 수신 연결이나 라우터 포트 설정을 끌 수 있다.

기본 네트워크 보존 한도는 2 GiB 또는 90일이며, 릴레이가 노드 폴더의 objects.sqlite에서 관리한다. Settings → Storage에서 값을 바꿀 수 있다. 로컬 보존 기간은 프로토콜 만료 기간보다 길 수 있어 나중에 보관소를 연 뒤 객체를 검사할 수 있다. 보존된 객체를 버리면 나중에 복구하지 못할 수 있지만, 이미 메일함에 저장된 편지에는 영향이 없다. 작업 증명은 CPU 코어 하나를 제외한 나머지와 GPU에서 실행한다. YNOTBIT_NO_GPU=1을 설정하면 CPU만 사용한다.

현재 한계

Ynotbit은 아직 개발 중인 소프트웨어다. 로컬 테스트는 문서 마이그레이션, 잘못된 객체, 프로토콜 픽스처, 실제 작업 증명, 컨트롤러 전달, 잠금과 재열기, 데스크톱 동작, 실제 루프백 릴레이 게시를 다룬다. 이는 독립적인 보안 감사나 공개 네트워크 상호운용성 인증이 아니다. 잠금은 보호된 키를 해제하고 접근을 닫지만, 화면에 표시된 평문이 Qt나 운영체제의 메모리, 스왑, 크래시 덤프, 스크린샷에서 모두 지워진다고 보장하지 않는다.

패키지로 제공하는 macOS 빌드는 Apple Silicon과 macOS 15.6 이상을 대상으로 하며 런타임 의존성을 포함한다. 임시 서명은 되어 있지만 Developer ID 서명이나 공증은 받지 않았다. 0.5.0부터 Windows 빌드도 작은 Winsock 계층(third_party/notbit/src/ntb-win32.c)을 통해 notbit 엔진을 실행한다. Windows에서는 앱이 노드에 정상 종료 신호를 보낼 수 없어 종료 시 노드를 강제로 끝낸다. 저장소가 대기열에 넣었지만 아직 기록하지 않은 작업은 버려진다. Linux 다운로드 파일은 단일 AppImage다. 편지 안에 넣는 그림을 제외한 파일 첨부와 CPU 병렬 처리량 설정은 구현되지 않았다.

.github/workflows/release.yml은 v* 태그가 푸시될 때마다(또는 수동 실행 시) Linux, macOS, Windows 빌드를 만들고 테스트한 뒤 패키징해 세 개의 아카이브를 GitHub 릴리스에 첨부한다. docs/ci/build.yml은 푸시와 PR마다 가벼운 빌드·테스트를 실행하되 패키징은 하지 않는 예전 템플릿이며, 아직 .github/workflows/에 연결되지 않았다.

검증 문서, 아키텍처 문서, 구현 계획, 제3자 저작물 고지를 참조하면 된다. ynotbit의 원본 코드는 MIT 라이선스이며, 함께 포함된 구성 요소에는 각각의 라이선스가 적용된다.