스마트스토어 판매자센터에서 주문을 엑셀로 내려받으려면 비밀번호를 정해야 합니다. 4~16자 비밀번호를 넣어야 받을 수 있고, 받은 파일은 엑셀에서 열 때 그 비밀번호를 묻습니다. 주문 파일에는 받는 분 이름, 전화번호, 주소, 공동현관 비밀번호까지 들어 있으니 이해가 가는 조치입니다.
문제는 이 파일을 다른 프로그램에 넣을 때입니다. 비밀번호 걸린 엑셀을 읽지 못하는 프로그램이라면 먼저 엑셀에서 비밀번호를 풀고 다시 저장해야 합니다. 매일 하는 일에 한 단계가 더 붙고, 비밀번호가 풀린 개인정보 파일이 컴퓨터에 하나 더 생깁니다. 반대로 비밀번호까지 받아 서버에서 푸는 방식은 주문 정보와 비밀번호를 함께 남에게 넘기는 일이 됩니다.
스마트스토어 송장 변환기는 둘 다 하지 않기로 했습니다. 비밀번호가 걸린 파일을 그대로 받아, 사용 중인 브라우저 안에서 풉니다. 파일도 비밀번호도 서버로 가지 않습니다. 이 글은 그 과정을 정리한 것입니다. 파일을 서버로 보내지 않는 구조 자체는 대화 파일을 서버로 보내지 않는 구조를 만들고 확인한 방법에 따로 썼습니다.
1. 비밀번호 걸린 엑셀은 zip이 아니다
보통의 엑셀 파일(.xlsx)은 사실 zip 파일입니다. 확장자를 .zip으로 바꾸면 안에 시트마다 XML 파일이 들어 있는 것을 볼 수 있습니다.
비밀번호를 걸면 모양이 완전히 바뀝니다. 파일 첫 바이트부터 zip이 아니라, 예전 .xls와 같은 복합 파일(CFB) 형식이 됩니다. 이 안에 스트림이 두 개 들어 있습니다.
| 스트림 | 내용 |
|---|---|
EncryptionInfo |
암호화 방식과 소금값(salt), 비밀번호 확인용 값이 적힌 XML |
EncryptedPackage |
원래 xlsx(zip) 전체를 암호화한 바이트 |
그래서 처음 할 일은 이 복합 파일을 읽어 두 스트림을 꺼내는 것입니다. 복합 파일은 512바이트 섹터를 사슬처럼 이어 붙인 작은 파일 시스템이라, 섹터 표(FAT)를 따라가며 조각을 모으면 됩니다. 구형 .xls도 같은 형식이라 머리 바이트만으로는 구별되지 않습니다. 그래서 두 스트림이 있는지로 “비밀번호 걸린 xlsx”와 “구형 xls”를 가립니다. 구형 xls라면 xlsx로 다시 저장해 달라고 안내합니다.
2. 스마트스토어 파일의 암호화 방식
실제로 내려받은 주문 파일의 EncryptionInfo를 열어 보면, 엑셀의 “암호로 보호”와 같은 ECMA-376 Agile 암호화입니다. 매개변수는 다음과 같았습니다.
| 항목 | 값 |
|---|---|
| 암호 | AES-256, CBC 모드 |
| 해시 | SHA-512 |
| 비밀번호 해시 반복 | 100,000회 |
| 데이터 조각 크기 | 4,096바이트 |
푸는 순서는 이렇습니다.
- 비밀번호를 키로 바꾼다. 소금값과 비밀번호(UTF-16)를 이어 SHA-512로 해시하고, 그 결과에 반복 번호를 붙여 다시 해시하기를 10만 번 합니다.
- 비밀번호가 맞는지 먼저 확인한다. 파일에는 “확인용 입력값”과 “그 값의 해시”가 각각 암호화되어 들어 있습니다. 1번의 키로 둘을 풀어서, 입력값의 해시가 저장된 해시와 같으면 비밀번호가 맞은 것입니다. 틀리면 여기서 “비밀번호가 맞지 않아요”라고 알립니다.
- 진짜 열쇠를 꺼낸다. 파일 내용은 비밀번호에서 만든 키가 아니라 무작위로 만든 별도의 열쇠로 암호화되어 있고, 이 열쇠가 비밀번호 키로 암호화되어 저장되어 있습니다. 이것을 풉니다.
- 4,096바이트씩 푼다. 원래 xlsx를 4,096바이트 조각마다 다른 초기값(IV)으로 암호화해 두었으므로, 조각 번호로 IV를 계산해 차례로 풉니다.
- zip인지 확인한다. 다 푼 결과가 zip 머리(
PK)로 시작하면 성공입니다. 그다음부터는 평범한 xlsx로 읽습니다.
비밀번호에 한글이나 대소문자가 섞여도 그대로 씁니다. 테스트에서 Pass한글1로 잠근 파일이 pass한글1로는 열리지 않는 것까지 확인했습니다.
3. 해시 10만 번이 7~10초 걸렸다
처음에는 브라우저에 들어 있는 암호 기능(WebCrypto)만으로 만들었습니다. 외부 라이브러리 없이 되니 가장 깔끔해 보였습니다. 시험 스크립트로 풀어 보니 결과는 맞았는데, 비밀번호를 넣고 파일이 열리기까지 7~10초가 걸렸습니다(Node 기준).
원인은 1번의 해시 10만 번이었습니다. WebCrypto의 해시 함수는 비동기라서, 한 번 부를 때마다 결과를 기다렸다가 다음 해시를 부르게 됩니다. 해시 계산 자체는 빠른데, 10만 번의 “부르고 기다리기”가 쌓여 시간이 됩니다.
해시를 동기로 계산하는 작은 라이브러리(@noble/hashes)의 SHA-512로 바꾸고, 같은 파일에 같은 비밀번호로 비교했습니다.
| 방식 | 비밀번호 확인까지 |
|---|---|
| WebCrypto 해시를 10만 번 비동기로 | 7~10초 |
| @noble/hashes 동기 SHA-512 | 약 0.6초 |
결과 바이트는 같았습니다. 반복할 때마다 새 배열을 만들지 않도록 “반복 번호 4바이트 + 앞 해시 64바이트” 크기의 버퍼 하나를 계속 다시 쓰는 것도 넣었습니다. 해시만 이 라이브러리로 하고, AES 복호화는 여전히 브라우저 내장 WebCrypto로 합니다.
동기 계산은 그동안 화면을 멈추게 합니다. 0.6초라도 버튼이 눌린 채 굳어 있으면 고장 난 것처럼 보입니다. 그래서 이 계산은 화면과 따로 도는 Web Worker에서 합니다. 화면은 “비밀번호로 파일 여는 중…“을 보여 주며 계속 움직입니다. 실제 Chrome에서 비밀번호를 넣고 파일을 열어 주문을 읽기까지 약 0.9초였습니다.
4. WebCrypto는 패딩 없는 AES를 풀어 주지 않는다
AES 쪽에서도 한 번 막혔습니다. 엑셀 암호화는 4,096바이트 조각을 패딩 없이 암호화합니다. 조각 길이가 이미 16바이트의 배수라서 덧붙일 것이 없기 때문입니다. 그런데 WebCrypto의 AES-CBC 복호화는 마지막에 PKCS#7 패딩이 반드시 있다고 가정하고, 없으면 오류를 냅니다.
방법은 패딩 블록을 직접 만들어 붙이는 것입니다. CBC 모드에서 블록 하나를 풀 때는 바로 앞 암호문 블록만 필요합니다. 그래서
- 조각의 마지막 암호문 블록을 IV로 삼아,
16이 16개 들어 있는 블록(올바른 PKCS#7 패딩 블록)을 같은 키로 암호화하고 - 그 결과를 조각 뒤에 붙인 다음
- 통째로 복호화합니다.
그러면 WebCrypto는 마지막에 정상적인 패딩이 있다고 보고 그 부분만 떼어 낸 뒤, 원래 조각을 그대로 돌려줍니다. 비밀번호 확인값과 열쇠를 풀 때도 같은 방법을 씁니다.
5. 테스트 파일도 직접 만들었다
이 기능을 시험하려면 비밀번호 걸린 스마트스토어 주문 파일이 여러 개 필요합니다. 실제 주문 파일에는 고객 정보가 들어 있어 저장소에 둘 수 없습니다. 그래서 반대 방향, 즉 암호화하는 코드를 따로 만들었습니다.
- 실제 발주발송관리 엑셀과 같은 72개 열, 같은 1행 안내문으로 가짜 주문 10건짜리 파일을 만들고
- 스마트스토어와 같은 매개변수(AES-256, SHA-512, 10만 회)로 암호화해
- 복합 파일로 감쌉니다.
이렇게 만든 파일이 진짜 엑셀 암호화와 같은지는 직접 짠 코드끼리 맞춰 봐서는 알 수 없습니다. 그래서 독립된 도구(msoffcrypto-tool)로 비밀번호 확인과 무결성 검사를 통과하는지, 틀린 비밀번호는 거부되는지 확인했고, Excel에서도 비밀번호를 넣어 열어 봤습니다. 가짜 주문에는 공동현관 비밀번호가 있는 주문, 합포장할 주문 두 건, 선물하기(구매자와 받는 분이 다름), 방문수령 요청처럼 변환에서 걸릴 만한 경우를 하나씩 넣었습니다.
6. 일부러 하지 않는 것, 아직 못 하는 것
- 비밀번호를 저장하지 않습니다. 매일 같은 비밀번호를 쓰는 셀러라면 기억해 두면 편하겠지만, 브라우저에 남겨 두면 그 기기를 쓰는 다른 사람도 주문 파일을 열 수 있게 됩니다. 페이지를 닫으면 파일과 비밀번호가 메모리에서 사라집니다.
- 무결성 값(HMAC)은 확인하지 않습니다. 파일이 중간에 바뀌었는지 확인하는 값인데, 비밀번호 확인값과 “푼 결과가 zip인지”로 잘못된 파일은 걸러지고, 이 도구는 파일을 고쳐 쓰지 않고 읽기만 합니다. 대신 잘린 파일, 깨진 파일은 “파일을 열지 못했어요”로 끝나도록 테스트했습니다.
- Agile 방식만 엽니다. 엑셀 2007의 예전 방식(Standard 암호화)은 아직 열지 못하고, 그런 파일이면 엑셀에서 암호를 푼 뒤 올려 달라고 안내합니다. 스마트스토어 파일은 Agile이라 해당하지 않습니다.
- 구형 .xls 송장 파일은 읽지 못합니다. 택배사 프로그램이 결과를 .xls로 내보내는 경우가 있는데, 지금은 xlsx로 다시 저장해 달라고 안내합니다.
열고 난 다음
파일을 열고 나면 송장 변환기가 하는 일은 두 가지입니다. 주문 파일만 올리면 CJ대한통운 CN PLUS 접수 파일을 만들고, 택배사에서 받은 송장번호 파일까지 올리면 주문과 송장을 맞춰 스마트스토어 일괄발송 파일을 만듭니다.
스마트스토어에서 받은 주문 엑셀이 있다면 스마트스토어 송장 변환기에 그대로 올려 보세요. 비밀번호를 넣는 칸이 나오고, 파일은 이 기기 밖으로 나가지 않습니다.