AI 해결 노트 · 2026-09-18 · 실측 2026-09-18
PDF에 암호 걸기 — 워드 메뉴로 거는 법, 이미 만들어진 PDF에 거는 법
한 줄로
3쪽짜리 더미 PDF에 열기 암호와 권한 암호를 걸어 봤습니다. 워드에서 PDF로 내보낼 때는 메뉴 안에 암호 칸이 있어 클릭만으로 되고(만들어진 파일은 128비트 AES), 이미 PDF인 파일은 파이썬으로 읽어 AES-256으로 다시 저장하면 됩니다. 다만 「인쇄 금지」 같은 권한 제한은 파이썬으로 그냥 다시 저장하는 것만으로 사라졌습니다.
이런 분께
- 급여 명세나 계약서 PDF를 메일로 보내야 해서 암호를 걸어야 하는 분
- 열기는 되게 하되 인쇄·편집만 막고 싶은 분
- 예전에 내가 걸어 둔 암호가 귀찮아져서 지우고 싶은 분
이 글에서 다루지 않는 것
남이 건 암호를 푸는 방법은 쓰지 않습니다. 아래 내용은 전부 제가 만든 더미 파일에 제가 암호를 걸고, 아는 암호로 다시 푸는 이야기입니다. 암호를 잊어버린 파일에 대해서도 방법을 적지 않았습니다. 뒤에 나오는 「권한 제한이 그냥 다시 저장하는 것만으로 없어진다」는 대목은 암호 푸는 요령이 아닙니다. 권한 제한을 믿고 맡기면 안 된다는 뜻으로 적었습니다.
실측 환경
| 항목 | 값 |
|---|---|
| OS | Windows 11 Home (10.0.26200) |
| 셸 | PowerShell 7 / Git Bash |
| Python | 3.12.10 |
| 파이썬 꾸러미 | pypdf 6.14.2, PyMuPDF 1.28.0 (MuPDF 1.29.0) |
| Word | 16.0 (Build 16.0.20326) |
| Excel | 16.0 (Build 20326.0) |
| Microsoft Edge | 153.0.4234.32 |
| 시험 파일 | 직접 만든 더미 PDF. 이름·번호는 지어낸 값(홍길동, 010-0000-0000) |
| 온라인 변환 사이트 | 쓰지 않았습니다 |
시험에 쓴 원본은 3쪽, 73,551바이트, 뽑히는 글자 163자짜리 더미 안내문입니다.
먼저 — PDF 암호는 두 가지입니다
PDF 규격에는 암호 자리가 둘 있습니다. 하나는 열기 암호(user password), 다른 하나는 권한 암호(owner password)입니다.
이번 시험에서 확인한 것은 이렇습니다. 열기 암호에 값을 넣으면 파일을 여는 순간 암호를 묻습니다. 열기 암호를 빈 문자열로 두고 권한 암호만 넣으면 암호를 묻지 않고 그냥 열리되, 인쇄·편집 같은 동작에 제한 표시가 붙습니다. 둘 중 무엇을 걸었는지에 따라 받는 사람이 겪는 일이 달라집니다.
원본 문서가 워드에 있다면 — 메뉴 안에 암호 칸이 있습니다
PDF를 워드에서 만들고 있다면 프로그램을 더 깔 것도, 명령을 칠 것도 없습니다. 순서는 이렇습니다.
- 워드에서 F12(다른 이름으로 저장)를 누릅니다.
- 「파일 형식(T)」을 PDF로 바꿉니다. 그러면 창 아래쪽에 「최적화 대상」과 「옵션(O)...」 단추가 나타납니다.
- 「옵션(O)...」을 누르면 「옵션」 창이 뜹니다. 맨 아래 PDF 옵션 묶음의 「암호로 문서 보호(N)」에 체크합니다.
- 「확인」을 누르면 「PDF 문서 암호화」 창으로 넘어갑니다. 암호를 두 번 넣고 확인하면 됩니다.

암호 칸 아래에 「암호는 6자에서 32자 사이여야 합니다」라고 적혀 있습니다. 「암호로 문서 보호」에 체크하면 그 위의 「PDF/A 호환(/)」이 흐려져 같이 못 켭니다.
이렇게 만든 PDF를 열어 보니 이랬습니다.
| 항목 | 값 |
|---|---|
| 크기 | 25,935바이트 |
| 암호를 물어보는가 | 예 (needs_pass = 1) |
| 암호화 방식 | Standard V4 R4 128-bit AES |
| 넣은 암호로 열기 | 됨 |
| 다른 암호로 열기 | 안 됨 |
여기서 건 것은 열기 암호입니다. 받는 사람이 파일을 열 때 암호를 물어봅니다.
이미 PDF인 파일에 암호 걸기
원본 문서가 없고 PDF만 손에 있으면 이야기가 달라집니다. 윈도우 11에도, 엣지에도 PDF에 암호를 거는 메뉴는 없습니다. 이럴 때 파이썬 pypdf를 씁니다.
from pypdf import PdfWriter
w = PdfWriter(clone_from=r"C:\경로\원본.pdf")
w.encrypt(user_password="yeolgi-1234",
owner_password="gwonhan-9876",
algorithm="AES-256")
with open(r"C:\경로\암호걸림.pdf", "wb") as f:
w.write(f)algorithm을 적어 주는 것이 중요합니다. 빼면 훨씬 오래된 방식으로 걸립니다.
algorithm | 결과 크기 | 파일에 기록된 암호화 방식 |
|---|---|---|
"AES-256" | 75,445바이트 | Standard V5 R6 256-bit AES |
| 안 적음 (기본값) | 74,447바이트 | Standard V2 R3 128-bit RC4 |
원본이 73,551바이트였으니 암호를 걸어 늘어난 몫은 1,894바이트입니다. 3쪽 문서 기준이고, 내용은 그대로 들어 있습니다.
PyMuPDF(fitz)로도 같은 일이 됩니다. 이쪽은 저장할 때 인자로 줍니다.
import fitz
d = fitz.open(r"C:\경로\원본.pdf")
d.save(r"C:\경로\암호걸림.pdf",
encryption=fitz.PDF_ENCRYPT_AES_256,
user_pw="yeolgi-1234",
owner_pw="gwonhan-9876",
permissions=532) # 인쇄·복사·읽어 주기 허용
d.close()이 파일은 74,719바이트가 나왔습니다. 암호화 방식은 pypdf의 AES-256 쪽과 같은 Standard V5 R6 256-bit AES입니다.
열기는 그냥 되게 하고 인쇄·편집만 막기
열기 암호 자리를 빈 문자열로 두고 권한 암호만 주면 됩니다. permissions_flag에 허용할 것만 적습니다. 적지 않은 것이 막히는 쪽입니다.
from pypdf import PdfWriter
from pypdf.constants import UserAccessPermissions as UAP
w = PdfWriter(clone_from=r"C:\경로\원본.pdf")
w.encrypt(user_password="", # 열기 암호는 없음
owner_password="gwonhan-9876",
permissions_flag=UAP.EXTRACT | UAP.EXTRACT_TEXT_AND_GRAPHICS,
algorithm="AES-256")
with open(r"C:\경로\권한제한.pdf", "wb") as f:
w.write(f)두 가지로 만들어 각각 열어 봤습니다. 아래 「허용/막힘」은 결과 파일을 다시 읽어 확인한 값입니다.
| 허용으로 준 것 | 기록된 permissions | 인쇄 | 내용 수정 | 글자 복사 | 주석 | 쪽 구성 |
|---|---|---|---|---|---|---|
| 인쇄 + 복사 | 2580 | 허용 | 막힘 | 허용 | 막힘 | 막힘 |
| 복사만 | 528 | 막힘 | 막힘 | 허용 | 막힘 | 막힘 |
파일 크기는 각각 75,439바이트와 75,438바이트입니다. 두 파일 모두 열 때 암호를 묻지 않습니다.
엣지에서 열면 이렇게 보입니다. 아래는 인쇄를 막은 쪽(permissions 528)입니다.

도구 모음 아래에 자물쇠 표시와 함께 「이 파일에 권한이 제한되어 있습니다. 일부 기능에 대한 액세스 권한이 없을 수 있습니다.」라는 띠가 붙고, 인쇄 단추와 형광펜·그리기 단추가 흐려집니다. 띠 오른쪽의 「사용 권한 보기」를 누르면 무엇이 막혔는지 목록이 나옵니다.

여덟 줄 가운데 「접근성을 위해 콘텐츠 복사 중」과 「콘텐츠 복사 중」, 「복사본 저장 중」에 체크가 있고, 「인쇄 중」·「서명」·「댓글 달기」·「양식 필드 채우기」·「파일 콘텐츠 편집하는 중」은 금지 표시입니다. 제가 준 값(복사만 허용)과 맞습니다.
권한 제한이 어디까지 막아 주는가
여기서 솔직히 적어 둘 것이 있습니다. 권한 제한은 프로그램이 지켜 주기로 한 약속입니다. 파일 자체는 AES-256으로 암호화되어 있지만 열기 암호가 빈 문자열이라, 프로그램은 암호 없이 내용을 다 읽습니다.
인쇄를 막은 파일(permissions 528)을 파이썬으로 열어 보니 이랬습니다.
needs_pass = 0 / is_encrypted = False
permissions = 528
인쇄 허용? False
그런데 글자는 뽑힙니다: '사내 안내문 (더미)\n작성 홍길동\n연락처 0' ... 총 163자
쪽 그림으로 렌더도 됩니다: 414 x 585 픽셀그리고 아무 것도 하지 않고 그냥 다시 저장하기만 해도 제한이 없어집니다.
import fitz
d = fitz.open(r"C:\경로\권한제한.pdf")
d.save(r"C:\경로\다시저장.pdf")
d.close()결과는 74,349바이트, 암호화 = None, permissions = -4(전부 허용)였습니다. 암호를 한 글자도 넣지 않았는데 그렇습니다.
그러니 권한 제한은 「실수로 인쇄하는 것을 막는 표시」 정도로 보시는 편이 맞습니다. 정말 못 열게 해야 하는 자료라면 열기 암호를 거셔야 합니다.
다른 프로그램에서 열면 무엇이 뜨나
열기 암호를 건 파일을 엣지로 열면 이 창이 뜹니다.

「암호 입력 — 이 파일은 암호로 보호되어 있습니다. 파일을 열려면 암호를 입력하세요.」이고, 뒤쪽 쪽 번호 칸은 「0 의 0」입니다. 본문은 하나도 안 보입니다.
파이썬에서는 프로그램마다 나오는 모양이 다릅니다. 둘 다 파일을 여는 것 자체는 성공하고, 내용을 만지려 할 때 막힙니다.
pypdf : PdfReader(...) 는 통과. is_encrypted = True
len(r.pages) 를 하면 → FileNotDecryptedError: File has not been decrypted
r.decrypt("wrong-pw") → 0 (안 맞음)
r.decrypt("yeolgi-1234") → 1 (열기 암호로 통과)
r.decrypt("gwonhan-9876") → 2 (권한 암호로도 통과)
PyMuPDF: fitz.open(...) 도 통과. needs_pass = 1
d[0].get_text() 을 하면 → ValueError: document closed or encrypted
d.authenticate("wrong-pw") → 0
d.authenticate("yeolgi-1234") → 2
d.authenticate("gwonhan-9876") → 4두 라이브러리 모두 열기 암호와 권한 암호를 다 받아 줍니다. 돌려주는 숫자로 어느 쪽이 맞았는지 알 수 있습니다. 참고로 워드가 만든 PDF에 authenticate를 하면 6이 나왔습니다. 워드는 두 자리에 같은 암호를 넣기 때문으로 보입니다.
내가 아는 암호로 지우기·바꾸기
암호를 알고 있으면 열어서 그냥 다시 저장하면 됩니다.
from pypdf import PdfReader, PdfWriter
r = PdfReader(r"C:\경로\암호걸림.pdf")
if r.is_encrypted:
r.decrypt("yeolgi-1234")
w = PdfWriter(clone_from=r)
with open(r"C:\경로\암호지움.pdf", "wb") as f:
w.write(f)PyMuPDF라면 이렇습니다.
import fitz
d = fitz.open(r"C:\경로\암호걸림.pdf")
d.authenticate("yeolgi-1234")
d.save(r"C:\경로\암호지움.pdf", encryption=fitz.PDF_ENCRYPT_NONE)
d.close()암호를 바꾸려면 헌 암호로 열고 새 암호로 저장합니다.
d = fitz.open(r"C:\경로\암호걸림.pdf")
d.authenticate("yeolgi-1234")
d.save(r"C:\경로\암호바꿈.pdf",
encryption=fitz.PDF_ENCRYPT_AES_256,
user_pw="sae-5678", owner_pw="gwonhan-9876")
d.close()바꾼 파일은 75,887바이트가 나왔고, 헌 암호 yeolgi-1234로는 authenticate가 0(안 열림), 새 암호 sae-5678로는 2가 나왔습니다.
암호를 지운 파일과 원본을 견줘 보니 쪽 수 3으로 같고, 세 쪽 모두 뽑히는 글자가 같았으며, 1쪽을 100dpi로 그린 827x1170 그림의 픽셀이 완전히 일치했습니다. 제가 확인한 것은 여기까지입니다. 나머지 두 쪽의 그림이나 문서 속성까지 같은지는 재지 않았습니다.
여러 파일을 한꺼번에 할 때
폴더 안의 PDF를 전부 처리하려면 같은 코드를 반복문에 넣으면 됩니다.
import glob, os
from pypdf import PdfWriter
for p in glob.glob(r"C:\경로\*.pdf"):
out = os.path.join(r"C:\경로\결과", os.path.basename(p))
w = PdfWriter(clone_from=p)
w.encrypt(user_password="yeolgi-1234", algorithm="AES-256")
with open(out, "wb") as f:
w.write(f)같은 더미 3개를 넣고 돌려 보니 0.06초에 끝났고, 세 파일 모두 75,445바이트로 암호가 걸렸습니다. glob.glob은 시작할 때 목록을 한 번 뜨므로 이 코드 자체가 결과 파일을 다시 집지는 않습니다. 다만 같은 폴더에 쓰면 다음에 또 돌릴 때 이미 암호가 걸린 파일이 입력에 섞이므로, 저장 폴더는 따로 두시는 편이 편합니다.
위 코드처럼 owner_password를 빼면 열기 암호와 같은 값이 권한 암호로도 들어갑니다. 결과 파일에 authenticate("yeolgi-1234")를 하면 6이 나와서, 두 자리가 다 맞았다는 뜻이 됩니다.
결과
| 무엇을 걸었나 | 어떻게 | 크기 | 암호화 방식 | 열 때 암호를 묻나 |
|---|---|---|---|---|
| 안 걸린 원본 | — | 73,551바이트 | 없음 | 아니요 |
| 열기 암호 | pypdf algorithm="AES-256" | 75,445바이트 | Standard V5 R6 256-bit AES | 예 |
| 열기 암호 | pypdf 기본값 | 74,447바이트 | Standard V2 R3 128-bit RC4 | 예 |
| 열기 암호 | PyMuPDF PDF_ENCRYPT_AES_256 | 74,719바이트 | Standard V5 R6 256-bit AES | 예 |
| 열기 암호 | 워드 메뉴 (암호로 문서 보호) | 25,935바이트 | Standard V4 R4 128-bit AES | 예 |
| 권한만 | pypdf, 복사만 허용 | 75,438바이트 | Standard V5 R6 256-bit AES | 아니요 |
| 암호 지움 | pypdf | 74,176바이트 | 없음 | 아니요 |
| 암호 지움 | PyMuPDF | 74,356바이트 | 없음 | 아니요 |
워드 쪽 크기가 작은 것은 원본 문서가 달라서입니다(워드에서 만든 1쪽 문서). 다른 줄과 견줄 수 있는 숫자가 아닙니다.
실패한 것
- 워드의
ExportAsFixedFormat을 자동화로 부르면서 암호를 주려고 했는데, 그런 인자가 없었습니다.
>>> d.ExportAsFixedFormat(OutputFileName=..., ExportFormat=17, Password="test-1234")
TypeError: _Document.ExportAsFixedFormat() got an unexpected keyword argument 'Password' 이 명령이 받는 인자는 OutputFileName, ExportFormat, OpenAfterExport, OptimizeFor, Range, From, To, Item, IncludeDocProps, KeepIRM, CreateBookmarks, DocStructureTags, BitmapMissingFonts, UseISO19005_1, FixedFormatExtClassPtr 열다섯입니다. 엑셀도 같았습니다(Type, Filename, Quality, IncludeDocProperties, IgnorePrintAreas, From, To, OpenAfterPublish, FixedFormatExtClassPtr, WorkIdentity). 암호 자리가 아예 없습니다.
SaveAs2(경로, FileFormat=17, Password="test-1234")로 PDF를 저장해 봤더니 파일은 25,257바이트로 만들어졌지만 암호가 걸려 있지 않았습니다(needs_pass = 0, 암호화 없음).Password는 워드 문서용 인자라 PDF에는 안 붙는 것으로 보입니다.- PyMuPDF에서
authenticate로 잠금을 푼 뒤needs_pass를 읽으면 잠금이 도로 걸립니다. 이것 때문에 처음에 「암호는 맞았는데 글자가 0자」라는 이상한 결과를 봤습니다.
auth 2
text len (1) 66
needs_pass -> 1
text len (2) 0 ← needs_pass 를 읽었더니 다시 잠김
auth again 2
text len (3) 66
is_encrypted False
text len (4) 66 ← is_encrypted 는 괜찮음 authenticate 뒤에는 needs_pass를 건드리지 않는 편이 낫습니다. PyMuPDF 1.28.0에서 본 동작입니다.
- 워드 화면을 자동으로 조작하는 동안 다른 창이 앞으로 튀어나오면 열려 있던 대화상자가 닫혀 버렸습니다. 한 번은 암호까지 넣었는데 「다른 이름으로 저장」 창으로 돌아온 채로 끝나 PDF가 안 만들어졌습니다. 위에 적은 네 단계는 손으로 눌러 가며 확인한 것입니다.
- 암호를 거는 시험과 여러 파일을 한꺼번에 처리하는 시험에서
Object count 30 exceeds defined trailer size 29라는 줄이 거듭 찍혔습니다(각각 4회, 3회). 경고가 나온 뒤에도 결과 파일의 암호화 방식과 암호 확인, 글자 뽑기는 정상이었습니다. 원인까지는 캐지 않았습니다.
확인하지 않은 것
- 엑셀에서 PDF로 내보낼 때 「옵션」 창에 암호 칸이 있는지는 화면으로 확인하지 못했습니다. 자동화 인자에 암호가 없다는 것만 확인했습니다.
- 한글(HWP)에서 PDF로 저장할 때의 암호 설정은 이 글에서 다루지 않았습니다.
- 암호가 걸린 PDF를 아크로뱃 리더나 한글 뷰어, 스마트폰에서 열면 어떤 문구가 뜨는지는 보지 않았습니다. 엣지와 파이썬 두 가지만 봤습니다.
- 128비트 RC4와 256비트 AES가 실제로 얼마나 다른 강도인지는 재지 않았습니다. 파일에 기록된 이름만 옮겨 적었습니다.
- 암호에 한글이나 특수문자를 넣었을 때 다른 프로그램에서 그대로 열리는지는 시험하지 않았습니다. 시험에 쓴 암호는 영문·숫자·붙임표(
yeolgi-1234꼴)뿐입니다. - 권한 제한이 아크로뱃처럼 규격을 지키는 프로그램에서 실제로 인쇄를 막는지는 엣지에서 단추가 흐려지는 것까지만 봤습니다. 인쇄를 눌러 보지는 않았습니다.
- 쪽 수가 많거나 그림이 많은 PDF에서 암호를 걸 때 얼마나 걸리는지는 재지 않았습니다. 3쪽짜리 더미 하나로만 했습니다.