무료 프라이버시 도구

파일 봉인하기

새로 만든 일회용 키로 파일을 암호화해 원하는 어떤 경로로든 보내세요. 그러면 키를 가진 사람이 바로 여기, 이 페이지에서 그것을 엽니다. 아무것도 업로드되지 않고, 크래킹할 패스프레이즈도 없으며, 무엇이든 저장되기 전에 안에 무엇이 들었는지 먼저 보게 됩니다.

이 탭 안에서만 실행됩니다. 이 페이지는 어떤 서버와도 통신할 수 없습니다.

모든 매개변수, 명시

암호 알고리즘
AES-256-GCM (WebCrypto), 청크마다 128비트 태그
브라우저 CSPRNG에서 나온 256비트, 봉인할 때마다 새로 생성, 한 번만 사용, 무엇으로부터도 유도되지 않음
청크 분할
암호화된 매니페스트(파일 이름, 크기, 형식), 그다음 1 MiB 청크로 나뉜 파일 — 청크마다 따로 인증됨
논스
32비트 무작위 봉인 솔트 ‖ 64비트 청크 카운터 — 한 파일 안에서 결코 반복되지 않으며, 애초에 키 자체가 일회용
인증 데이터
16바이트 헤더 전체와 각 청크의 인덱스, 그리고 전체 청크 개수 — 청크를 재배열하거나 잘라내거나 이어 붙이면 복호화가 깨집니다
키 문자열
base64url, 47자: 32바이트 키에 3바이트 SHA-256 체크섬을 더한 것 — 오타는 쓰레기 데이터를 만들어내는 대신 깔끔하게 실패합니다

이 도구가 하는 일에 대한 정직한 답

모든 것은 내 브라우저 안에서 일어납니다.

봉인도 열기도 파일을 이 페이지의 메모리로 읽어 들여, 브라우저에 내장된 WebCrypto 엔진으로 그 자리에서 AES-256-GCM을 실행하고, 결과를 다운로드로 돌려줍니다. 아무것도 업로드되지 않습니다. 계정도 없고, 서버 측 처리도 없습니다. 이 사이트의 다른 페이지들과 달리, 이 페이지는 쿠키 없는 방문 카운터조차 불러오지 않습니다. 어떤 종류의 분석 도구도 없습니다.

이것은 그저 약속이 아닙니다. 이 페이지는 Content-Security-Policy와 함께 전송되며, 그 정책은 브라우저가 이 사이트 자체의 정적 파일만 가져오도록 허용합니다. 내 파일도, 내 키도, 그 밖의 무엇도 어떤 서버로든, 저희 서버를 포함해 보낼 방법이 없습니다. 봉인하는 동안 브라우저의 개발자 도구를 열어 보면 요청이 0건인 것을 보게 됩니다. 가장 확실한 증명을 원하면, 툴박스를 설치하고 비행기 모드에서 봉인해 보세요. 네트워크를 끄면 아무것도 나갈 수 없습니다.

키가 전부입니다 — 그리고 저희는 그것을 결코 갖지 않습니다.

봉인할 때마다 브라우저에서 새 무작위 256비트 키가 생성됩니다. 그 키는 한 번만 표시되고 어디에도 보관되지 않습니다. 저희 시스템에도(애초에 관여하는 시스템이 없습니다), 브라우저 저장소에도, 봉인된 파일 안에도 없습니다. 추측할 패스프레이즈도, 무차별 대입할 것도 없습니다. 키와 파일을 함께 쥔 사람은 열 수 있습니다. 그렇지 못한 사람은 열 수 없습니다.

여기에는 냉정한 결과가 따릅니다. 키를 잃으면 파일도 사라집니다. 재설정도, 지원 티켓도, 복구도 없습니다. 저희가 불친절해서가 아닙니다. 저희가 복구해 줄 수 있는 사본이란 곧 누군가 훔치거나 내놓으라고 요구할 수 있는 사본이니까요.

키 링크는 결코 서버에 닿지 않습니다.

공유 링크는 키를 URL의 # 뒤에 둡니다. 그 부분, 곧 프래그먼트는 브라우저 안에 머뭅니다. 브라우저가 어떤 서버로 보내는 내용에도 결코 포함되지 않습니다. 저희 서버든 다른 누구의 서버든 마찬가지입니다. 링크에 키가 담긴 채 이 페이지가 열리면, 페이지는 키를 읽고 “열기” 탭으로 전환한 뒤, 곧바로 주소창에서 키를 지웁니다. 그래서 보이는 URL이나 브라우저 방문 기록에 남지 않습니다.

그래도 링크와 봉인된 파일을 모두 가진 사람은 누구나 그것을 열 수 있습니다. 이 페이지가 파일과 키를 서로 다른 경로로 보내라고 말하는 이유입니다.

무엇이든 저장되기 전에, 안에 무엇이 들었는지 먼저 봅니다.

여는 일은 두 단계로 이루어집니다. 먼저 페이지는 작은 매니페스트, 곧 원래 파일 이름, 크기, 형식만 복호화합니다. 그리고 그것을 보여주며, 코드를 실행할 수 있는 형식(프로그램, 스크립트, 설치 파일, 매크로 문서, HTML)이나 invoice.pdf.exe처럼 이중 확장자로 위장한 이름에는 큼직한 경고를 붙입니다. 직접 복호화를 클릭하기 전까지는 아무것도 기록되지 않습니다. 페이지가 복호화된 내용을 스스로 열거나 표시하는 일도 없습니다. 파일을 다운로드로 건넬 뿐입니다.

암호화가 무엇을 증명하고 무엇을 증명하지 못하는지 분명히 해두세요. 봉인된 파일은 전송 중에 내용이 지켜집니다. 하지만 봉인 자체는 누가 보냈는지도, 내용이 안전한지도 전혀 말해주지 않습니다. 예상치 못한 봉인 파일은 예상치 못한 첨부 파일과 똑같은 정도로 의심하세요.

신뢰의 경계가 실제로 어디에 있는가.

지금 실행되는 것은 이 웹사이트가 여러분에게 내려보낸 코드입니다. sealby.app이나 그곳으로 향하는 연결이 침해된다면, 악의적인 페이지가 여러분이 넣은 것을 읽어낼 수 있습니다. 이는 웹 기반 암호화 도구 전부에 해당하는 사실이고, 저희는 아닌 척하기보다 말하는 쪽을 택합니다. 그래서 저희가 하는 일은 이렇습니다. 이 페이지는 정적 파일이고, 제3자 코드는 넣지 않습니다. 설치된 툴박스는 이미 내려받은 버전을 계속 쓸 수 있게 해줍니다. 그리고 포맷은 아래에 문서화되어 있어, 독립적인 도구를 만들어 붙일 수 있습니다.

내 기기 역시 그 경계 안에 있습니다. 페이지 접근 권한이 있는 브라우저 확장 프로그램이나 기기에 있는 악성 코드는, 어떤 페이지가 읽을 수 있는 것이면 무엇이든 읽을 수 있습니다. 봉인된 파일은 내용을 숨기지만, 전부를 숨기지는 않습니다. 그 파일을 가진 사람은 누구나 크기(대략 원본의 크기)와 그것이 Sealby로 봉인된 파일이라는 사실을 알 수 있습니다.

쉬운 말로 정리한 한계

  • 키를 잃으면 곧 파일을 잃습니다. 예외는 없으며, 그것이 설계입니다.
  • 저희는 내 파일도 키도 볼 수 없으므로, 악성 코드가 있는지 대신 검사해 줄 수도 없습니다. 파일 형식 경고는 파일 이름에만 기반합니다. 안전 보증이 아닙니다.
  • 봉인된 파일과 키를 모두 가진 사람은 누구나 열 수 있습니다. 이 도구는 그 사람이 누구인지 알지도, 확인하지도 않습니다.
  • 봉인된 파일의 크기는 원본 파일의 크기를 대략 드러냅니다.
  • 봉인 한 번에 파일 하나, 최대 100 MB. 여러 파일은 먼저 압축하세요.

포맷, 바이트 단위로

기술 독자가 이 페이지의 출력을 독립적으로 검증하거나, Python 서른 줄로 .sealed 파일을 여는 데 필요한 전부:

bytesfieldcontents
0–7magicASCII "SEALBY-W"
8version0x01 — 그 밖의 값은 “더 새로운 버전으로 만들어짐”으로 거부됩니다
9algorithm0x01 = AES-256-GCM
10–13봉인 솔트4바이트, CSPRNG, 봉인마다 새로 생성
14–15reserved반드시 0이어야 함
16–끝청크 프레임각각: uint32 빅 엔디언 암호문 길이, 그다음 AES-GCM 암호문 + 16바이트 태그

청크 0은 매니페스트입니다: UTF-8 JSON {"name":…,"size":…,"type":…}. 청크 1…N−1은 1 MiB 조각으로 나뉜 파일입니다. N개 중 i번째 청크에 대해: nonce = salt ‖ uint64 빅 엔디언 i; 인증 데이터 = header ‖ uint64 빅 엔디언 i ‖ uint64 빅 엔디언 N. 그래서 변조, 절단, 재배열, 위치 이동, 파일 간 이어 붙이기가 모두 인증에 실패합니다. 각 경우는 커밋된 네거티브 테스트로 증명되어 있습니다.

키 문자열: 32바이트 키 뒤에 그 SHA-256의 앞 3바이트를 붙이고 전체를 base64url(패딩 없음)로 인코딩한 것으로, 총 47자입니다. 오타는 쓰레기 데이터를 만들어내는 대신 체크섬에서 실패합니다.

참조 열기 구현 (Python, cryptography 라이브러리)
import base64, hashlib, json, struct, sys
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

raw = open(sys.argv[1], "rb").read()
assert raw[:8] == b"SEALBY-W" and raw[8] == 1 and raw[9] == 1
assert raw[14:16] == b"\x00\x00"
header, salt = raw[:16], raw[10:14]
frames, off = [], 16
while off < len(raw):
    (n,) = struct.unpack(">I", raw[off:off + 4]); off += 4
    frames.append(raw[off:off + n]); off += n
assert off == len(raw)

kb = base64.urlsafe_b64decode(sys.argv[2] + "=")   # 47-char key string
key, check = kb[:32], kb[32:35]
assert hashlib.sha256(key).digest()[:3] == check    # typo check

N = len(frames)
def chunk(i):
    nonce = salt + struct.pack(">Q", i)
    aad = header + struct.pack(">QQ", i, N)
    return AESGCM(key).decrypt(nonce, frames[i], aad)

manifest = json.loads(chunk(0))
data = b"".join(chunk(i) for i in range(1, N))
assert len(data) == manifest["size"]
open(manifest["name"], "wb").write(data)
print("decrypted ->", manifest["name"])

이것은 이동 중인 파일을 위한 것입니다. 금고는 머무는 파일을 위한 것입니다.

봉인은 어딘가로 가는 길 위의 파일을 지킵니다. Sealby는 머무는 모든 것을 지킵니다: iPhone의 암호화 금고 속 사진, 파일, 메모. 계정도 서버도 없이, 오직 나만 읽을 수 있습니다.

App Store에서 다운로드

iPhone과 iPad · iOS 17+ · 무료