PC에 가지고 있는 데이터는 복사가 손쉽게 이루어진다.
복사된 데이터는 P2P 프로그램이나 웹하드 디스크를 통해 널리 유포 된다.
이렇게 저작권이 있는 Content, data의 무단 복제를 막기 위해 발표한 것이 DRM이 되시겠다.
자 DRM이란 무었인가?
Digital Rights Management의 약자로, 사전적의미는 "디지털 권리 관리(?)"이다.
OMA에서 이 DRM을 Mobile 환경에 맞게 표준화 하여 OMA DRM 1.0을 발표했다.
OMA DRM 1.0
OMA DRM 1.0은 아래와 같이 각 Level로 나뉜다. Level은 선택사항라서 하나를 선택하면 되는 것이다.
Forward Lock
Combined Delivery
Separated Delivery
Forward Lock(이하 FL)
FL은 Header + Content 구조로 되어 있고, "boundary"가 두 부분을 나누어 준다.
Header부분에는 Header Size, 암호 알고리즘, Vendor 정보 등이 들어 간다.
암호 알고리즘이라 해봐야, FL에서는 binary, Base64.... 두 가지 정도가 더 있었는데..기억이;;
대부분 이 두가지를 쓴다.
DRM Engine의 Agent에서는 이 파일은 다른 곳으로 Forwarding할 수 없도록 막아 줘야 한다.
그래서 이름이 Forward Lock이라는거...
Combined Delivery(이하 CD)
CD는 FL과 같은 구조에 Rights라는 License개념의 Data가 추가 된다.
이 Rights는 이 Content의 Permission과 Constraint 정보 및 Content를 Decrypt할 수 있는 Key 값을 포함한다. (Permission은 Play, Display과 같은 값으로 Content를 사용하는 방법과 관련되었고, Constraint는 Timebase, Unlimited, Interval, Count 과 같은 값으로 Content의 사용 기간(?)이라고 보면 되겠다.
Content는 AES-128-CBC 알고리즘으로 암호화 되어 전송되며, 복호화 Key는 Rights에 포함되어 있다.
해당 Content 관련 Rights를 소두 소진하게 되면, Rights는 갱신할 수 없으며, Content는 못 쓰게 된다. FL과 마찬가지로 Forwarding할 수 없다.
Separated Delivery(이하 SD)
SD는 Content와 Rights를 따로 받는다. Content와 Rights의 연결고리는 각각의 Header에 있는 Unique한 CID로 찾는다. 암호 알고리즘은 CD와 마찬가지로, AES-128-CBC를 사용한다.
Rights 갱신시에는 Content의 Header에 있는 Rights URI를 이용하여 다시 받으면 된다.
국내에서 멜론을 통해 받는 *.dcf가 SD를 customizing하여 사용하는 예로 볼 수 있다.
DRM 1.0은 발표 된지 오래 되었으며, 이제 v1.0으로는 돈벌기 힘들다. ㅎㅎㅎ
WMDRM(Windows Media Digital Rights Management)
DRM이 세계적인 Issue로 떠오르면서 Microsoft에서도 독자적인 DRM을 발표하였다.
이름하여, WMDRM.
초기버전 WMDRM은 ASF format 기반의 WMA, WMV파일을 시작하였으며, 차기 버전에서는
Image, Office 파일에 걸쳐 전반적인 데이터에도 적용할 것을 암시했다.
대체 이 WMDRM 이란 무엇이며, 어떻게 생겨먹은지를 알아보도록 하자.
(이 내용에서는 ASF포맷 기반의 WMA, WMV만 보도록 한다.)
참고로, WMDRM에서 손뗀지 좀 오래되다 보니, 가물가물한 부분은 살짝 생략하거나, 대충(ㅡ.ㅡ?) 설명하겠다.
1. ASF Format
WMDRM을 알기 위해서는 그 전에 ASF Format을 알아야 한다.
(ASF Specification Download URL:
http://www.microsoft.com/windows/windowsmedia/forpros/format/asfspec.aspx)
ASF 포맷의 구조는 이러하다. (<..>은 Optional)
----------------------------------
Header
- File Properties Object
- Stream Properties Object 1
...
...
- Stream Properties Object N
<Other Header Objects>
----------------------------------
Data Object
- Data Packet 1
- ...
- ...
- Data Packet M
----------------------------------
<Other top-level objects>
- Index Object 1
- ...
- Index Object K
- Simple Index Object 1
- ...
- Simple Index Object L
----------------------------------
2. Header
Header에는 이 파일의 출처가 어디며 어떻게 재생해야 하고, 시간은 어떻게 되는 등등 파일의 모든 정보가
들어 있다. Header의 Object는 Object별로 순서가 있는게 아니기 때문에 GUID라는 값을 사용해서 각 종류별로 Pasing을
하도록 해야 한다.
ASF파일의 Objects는 기본적으로 다음과 같이 구성된다.
----------------------------------
Object ID(GUID) - 128 bit
----------------------------------
Object Size - 64 bit
----------------------------------
Object Data - Object Size bit
----------------------------------
이제 Header를 Pasing해 보자.
ASF파일은 모두 Header Object로 시작한다.
Header부분에서도 가장 앞에 있어야 하며, 이 Header에 몇개의 Header Object가 있으며, Header의
전체 길이(Data Object의 바로 앞까지)를 나타낸다.
Name |
GUID |
ASF_Header_Object |
75B22630-668E-11CF-A6D9-00AA0062CE6C |
ASF_Data_Object |
75B22636-668E-11CF-A6D9-00AA0062CE6C |
ASF_Simple_Index_Object |
33000890-E5B1-11CF-89F4-00A0C90349CB |
ASF_Index_Object |
D6E229D3-35DA-11D1-9034-00A0C90349BE |
ASF_Media_Object_Index_Object |
FEB103F8-12AD-4C64-840F-2A1D2F7AD48C |
ASF_Timecode_Index_Object |
3CB73FD0-0C4A-4803-953D-EDF7B6228F0C |
<표 1. Top Level ASF Object GUID>
파일을 Open해서 GUID(128bit)를 가져오면 첫번째로 ASF_Header_Object가 나온다.
Field name |
Field type |
Size (bits) |
Object ID |
GUID |
128 |
Object Size |
QWORD |
64 |
Number of Header Objects |
DWORD |
32 |
Reserved1 |
BYTE |
8 |
Reserved2 |
BYTE |
8 |
<표 2. ASF Header Object>
그 다음 64bit는 Object Size이다. 현재 Object의 길이를 말해준다. 여기서 Object의 길이는 GUID로부터 끝나는 부분까지의
길이이다. 그 다음에 나오는 Number of Header Objects는 아래의 <표3>에 열거된 Header Object들의 갯수를 나타낸다.
이 Number of Header Objects의 수 만큼 loop를 돌려서 각 Object 값들을 pasing하면 되겠다.
Name |
GUID |
ASF_File_Properties_Object |
8CABDCA1-A947-11CF-8EE4-00C00C205365 |
ASF_Stream_Properties_Object |
B7DC0791-A9B7-11CF-8EE6-00C00C205365 |
ASF_Header_Extension_Object |
5FBF03B5-A92E-11CF-8EE3-00C00C205365 |
ASF_Codec_List_Object |
86D15240-311D-11D0-A3A4-00A0C90348F6 |
ASF_Script_Command_Object |
1EFB1A30-0B62-11D0-A39B-00A0C90348F6 |
ASF_Marker_Object |
F487CD01-A951-11CF-8EE6-00C00C205365 |
ASF_Bitrate_Mutual_Exclusion_Object |
D6E229DC-35DA-11D1-9034-00A0C90349BE |
ASF_Error_Correction_Object |
75B22635-668E-11CF-A6D9-00AA0062CE6C |
ASF_Content_Description_Object |
75B22633-668E-11CF-A6D9-00AA0062CE6C |
ASF_Extended_Content_Description_Object |
D2D0A440-E307-11D2-97F0-00A0C95EA850 |
ASF_Content_Branding_Object |
2211B3FA-BD23-11D2-B4B7-00A0C955FC6E |
ASF_Stream_Bitrate_Properties_Object |
7BF875CE-468D-11D1-8D82-006097C9A2B2 |
ASF_Content_Encryption_Object |
2211B3FB-BD23-11D2-B4B7-00A0C955FC6E |
ASF_Extended_Content_Encryption_Object |
298AE614-2622-4C17-B935-DAE07EE9289C |
ASF_Digital_Signature_Object |
2211B3FC-BD23-11D2-B4B7-00A0C955FC6E |
ASF_Padding_Object |
1806D474-CADF-4509-A4BA-9AABCB96AAE8 |
<표 3. Header Object GUIDs>
각 Object들의 Field 값들은 모두 다르니 제일 처음에 언급한 ASF Specification의 [3. ASP top-level Header Object]
항목을 참고해서 pasing하시면 되겠다. Header pasing은 끝. ㅡ,.ㅡ;
3. Data Object
Data Object의 시작점은 Header Pasing에서 제일 처음에 나오는, ASF Header 데이터에서 가져온 Header Size값 만큼,
파일을 seek 하면 된다. ASF Header 특성상 Header Object들이 단위 별로 끊어져 있으므로, Header Pasing이 끝나는 부분에서
Data Object라고 생각하여 사용하지말고, 꼭 Header Size를 이용한 부분에서 Data Object라고 보는게 낫다.
Data Object 역시 GUID가 있다. <표 1>에서 두번째에 자리잡은 ASF_Data_Object 값이 그것이다.
Field name |
Field type |
Size (bits) |
Object ID |
GUID |
128 |
Object Size |
QWORD |
64 |
File ID |
GUID |
128 |
Total Data Packets |
QWORD |
64 |
Reserved |
WORD |
16 |
Data Packets |
See section 5.2 |
varies |
<표 4. Data Object>
Object Size는 Data Object의 전체 사이즈를 나타낸다. File ID값은 unique한 값이라는데 그닥 재생하는데 상관은 없는듯 하다.
Total Data Packets이 있는데, 이는 Header Object중 ASF_File_Properties Object의 Packet Count와 일치해야 한다.
이 Packet에 대해서는 아래에서 자세히 알아보도록 한다.
그리고 Reserved는 임시로 마련해둔 값이므로 무시하고, Data Packets이라는 부분이 바로 재생하는 데이터, 즉 Packets의
실제 데이터가 들어가는 부분이다.
하나의 Packet의 Size는 64KB를 넘으면 안된다. 그래서 이를 넘는 크기의 Media인 경우 Packet단위로 짤려서 존재하며,
Packet의 총 갯수가 필요한 것이다.
4. Packet
Packet은 아래와 같이 구성된다.
---------------------------------------------------- ----------------------------------------------------
Error Correction Data(Optional) Error Correction Data(Optional)
---------------------------------------------------- ----------------------------------------------------
Payload Parsing Information
---------------------------------------------------- Or Opaque Data
Payload Data
---------------------------------------------------- ----------------------------------------------------
Padding Data(Optional) Padding Data(Optional)
---------------------------------------------------- ----------------------------------------------------
두가지 Structure가 있는데, 우측의 Opaque Data... ㅡ,.ㅡ 뭔지...;; 어떻게 Pasing하란 말인가;;; 일단 우측은 Pass.
Error Correction Data와 Padding Data는 Spec을 참고 한다. Optional이므로 그닥 중요한 내용은 아니다.
이제 Packet도 Pasing을 해보자.
Error Correction Data가 Optional이긴 하지만, 있는지 없는지를 확인 해야 한다.
Field name |
Field type |
Size (bits) | |
Error Correction Flags |
BYTE |
8 | |
Error Correction Data Length |
|
4 (LSB) | |
Opaque Data Present |
|
1 | |
Error Correction Length Type |
|
2 | |
Error Correction Present |
|
1 | |
Error Correction Data |
BYTE |
varies |
<표 5. Error Correction Data>
만약 Error Correction Flags가 0이면 이 항목은 Pass, 0이 아니면, 스펙에 따라 Pasing하자.
그 다음이 Payload Pasing Information 이다.
Field name |
Field type |
Size (bits) | |
Length Type Flags |
BYTE |
8 | |
Multiple Payloads Present |
|
1 (LSB) | |
Sequence Type |
|
2 | |
Padding Length Type |
|
2 | |
Packet Length Type |
|
2 | |
Error Correction Present |
|
1 | |
Property Flags |
BYTE |
8 | |
Replicated Data Length Type |
|
2 (LSB) | |
Offset Into Media Object Length Type |
|
2 | |
Media Object Number Length Type |
|
2 | |
Stream Number Length Type |
|
2 | |
Packet Length |
BYTE, WORD or DWORD |
0, 8, 16, 32 | |
Sequence |
BYTE, WORD or DWORD |
0, 8, 16, 32 | |
Padding Length |
BYTE, WORD or DWORD |
0, 8, 16, 32 | |
Send Time |
DWORD |
32 | |
Duration |
WORD |
16 |
<표 6. Payload Information>
너무 긴데. 하나하나 설명을 해야 하나.... 휴..
자세한 내용은 꼭!!! Spec을 같이 봐달라... 표가 너무 많다.
먼저 Length Type Flags인 1Byte(8bit)를 읽어서 Multiple Payloads Present 값 부터,
Error Correction Present까지 5개의 항목에 해당하는 값을 구한다.
Multiple Payloads Present 는 Multiple Payload인지 아닌지,
(참고로 Packet은 이 Payload를 위한 집(house)라고 생각하면 되겠다.
WMA파일인 경우 1개의 Packet에 1개의 Payload가 일반적인데, WMV 와 같은 경우에는 Multiple Payload라고
해서 하나의 Packet내에 Payload가 두 개 존재한다. 아마도 음성과 영상이 포함되었을 것이다.)
Sequence Type은 Sequence Field의 단위(Sequence Field가 없다, BYTE, WORD, DWORD 중 하나)
Padding Length Type의 단위(Padding Length Field가 없다, BYTE, WORD, DWORD 중 하나)
Packet Length Type 단위(Packet Length Field가 없다, BYTE, WORD, DWORD 중 하나)
Error Correction Present(Error Correction의 유무)
등을 알 수 있다.
이와 같은 방법으로 Pasing한다. 스펙에 쉽게 잘 나와 있다.
5. Payload
이노무 시키... Payload만 하면 ASF Format은 끝이다.
자... Payload는 어떻게 생겼냐... 하면 이렇게 생겼다. 못생긴기..ㅡ.,ㅡㅋ 쩝.
각 Payload는 표와 같이 구성된다.
Field name |
Field type |
Size (bits) |
Stream Number |
BYTE |
8 |
Media Object Number |
BYTE, WORD, or DWORD |
0, 8, 16, 32 |
Offset Into Media Object |
BYTE, WORD, or DWORD |
0, 8, 16, 32 |
Replicated Data Length |
BYTE, WORD, or DWORD |
0, 8, 16, 32 |
Replicated Data |
BYTE |
varies |
Payload Data |
BYTE |
varies |
<표 7. Payload>
Payload에는 Single Payload와 Multiple Payload, 그리고 각각 Compressed Payload라는게 있다.
Payload 부분은 다음에 다시 자세히 분석해서 올려보도록 하겠다.
6. ASF에서 WMDRM 이 되는 과정.
오늘 WMDRM 스펙을 구했다. 이 부분을 다시 정리해서 올리도록하겠다. (2008-12-18)
원래글.
(이러한 ASF 구조에서 WMDRM은 Header부분의 Stream Properties Object에 WMDRM과 관련된
Object가 두개 정도 추가가 된다. Object Name과 GUID는 WMDRM PD(porting Device)의 문서에 나와 있다.
그리고 Packet의 Payload의 내용이 암호화 되어 있다.
ASF 파일의 Payload의 Decrypt 방법은 마지막 8Byte를 이용해서 Payload 별로 Decrypt하는데,
WMDRM에서는 Payload를 Decrypt하기 위해 또 다른 Key가 필요하다.
HDS 파일이라는 WMDRM에서 사용하는 License Management 파일이 있다. WMA 파일의 Header에서 KID를 가져온다. 이 값을 이용해 HDS 파일에서 Key를 꺼내고, Device의 Private Key를 이용해 복호화 해야 한다.)
흠..ㅡ,.ㅡ; 너무 간단하게 적었다.
WMDRM 문서를 찾게되면, 다시 정교하게 update를 하겠다. }
결국 가장 중요한 Payload와 WMDRM 에 관련된 사항이 빠졌다;;
문서를 꼭 찾아서 다시 올려보도록 하겠다. ㅡ,.ㅡ 시간이 더 필요하군아.
오랫만에 되새기니까, 가물가물하다. 암튼 WMDRM 기억에 남을 만하다.
From. 다은이 아부지 블로그
http://prey012.tistory.com/