@@ -41,16 +41,31 @@ export class Client {
41
41
42
42
#key?: { forDecrypt : CryptoKey ; forSign : CryptoKey } ;
43
43
44
- static async fromPacked ( data : Uint8Array , format : 'WVDv2' = 'WVDv2' ) {
45
- if ( format !== 'WVDv2' ) throw new Error ( 'Only WVDv2 is supported' ) ;
46
- const parsed = parseWvd ( data ) ;
47
- const pcks1 = `-----BEGIN RSA PRIVATE KEY-----\n${ fromBuffer ( parsed . privateKey ) . toBase64 ( ) } \n-----END RSA PRIVATE KEY-----` ;
48
- const key = fromText ( pcks1 ) . toBuffer ( ) ;
49
- const type = types . get ( parsed . deviceType ) ;
50
- const securityLevel = parsed . securityLevel as SecurityLevel ;
51
- const client = new Client ( parsed . clientId , type , securityLevel ) ;
52
- await client . importKey ( key ) ;
53
- return client ;
44
+ static async fromPacked ( data : Uint8Array , format : 'wvd' | 'azot' = 'azot' ) {
45
+ if ( format === 'wvd' ) {
46
+ const parsed = parseWvd ( data ) ;
47
+ const pcks1 = `-----BEGIN RSA PRIVATE KEY-----\n${ fromBuffer ( parsed . privateKey ) . toBase64 ( ) } \n-----END RSA PRIVATE KEY-----` ;
48
+ const key = fromText ( pcks1 ) . toBuffer ( ) ;
49
+ const type = types . get ( parsed . deviceType ) ;
50
+ const securityLevel = parsed . securityLevel as SecurityLevel ;
51
+ const client = new Client ( parsed . clientId , type , securityLevel ) ;
52
+ await client . importKey ( key ) ;
53
+ return client ;
54
+ } else if ( format === 'azot' ) {
55
+ const parsed = JSON . parse ( fromBuffer ( data ) . toText ( ) ) ;
56
+ const clientId = ClientIdentification . fromObject (
57
+ parsed . data . clientIdentification ,
58
+ ) ;
59
+ const client = new Client (
60
+ clientId ,
61
+ parsed . data . type ,
62
+ parsed . data . securityLevel ,
63
+ ) ;
64
+ await client . importKey ( parsed . data . privateKey ) ;
65
+ return client ;
66
+ } else {
67
+ throw new Error ( 'Unsupported format' ) ;
68
+ }
54
69
}
55
70
56
71
static async fromUnpacked ( id : Uint8Array , key : Uint8Array , vmp ?: Uint8Array ) {
@@ -69,11 +84,11 @@ export class Client {
69
84
}
70
85
71
86
constructor (
72
- id : Uint8Array ,
87
+ id : Uint8Array | ClientIdentification ,
73
88
type : ClientType = CLIENT_TYPE . android ,
74
89
securityLevel : SecurityLevel = 3 ,
75
90
) {
76
- this . id = ClientIdentification . decode ( id ) ;
91
+ this . id = ArrayBuffer . isView ( id ) ? ClientIdentification . decode ( id ) : id ;
77
92
this . signedDrmCertificate = SignedDrmCertificate . decode ( this . id . token ) ;
78
93
this . drmCertificate = DrmCertificate . decode (
79
94
this . signedDrmCertificate . drmCertificate ,
@@ -92,29 +107,46 @@ export class Client {
92
107
return [ id , key ] ;
93
108
}
94
109
95
- async pack ( format : 'WVDv2' = 'WVDv2' ) {
96
- if ( format !== 'WVDv2' ) throw new Error ( 'Only WVDv2 is supported' ) ;
97
- const id = ClientIdentification . encode ( this . id ) . finish ( ) ;
98
- const key = await this . exportKey ( ) ;
99
- const keyDer = fromBuffer ( key )
100
- . toText ( )
101
- . split ( '\n' )
102
- . map ( ( s ) => s . trim ( ) )
103
- . slice ( 1 , - 1 )
104
- . join ( '\n' ) ;
105
- const keyDerBinary = fromBase64 ( keyDer ) . toBuffer ( ) ;
106
- const [ type ] = types . entries ( ) . find ( ( [ , type ] ) => type === this . type ) ! ;
107
- const wvd = buildWvd ( {
108
- clientId : id ,
109
- deviceType : type ,
110
- securityLevel : this . securityLevel ,
111
- privateKey : keyDerBinary ,
112
- } ) ;
113
- return wvd ;
110
+ async pack ( format : 'wvd' | 'azot' = 'azot' ) {
111
+ if ( format === 'wvd' ) {
112
+ const id = ClientIdentification . encode ( this . id ) . finish ( ) ;
113
+ const key = await this . exportKey ( ) ;
114
+ const keyDer = fromBuffer ( key )
115
+ . toText ( )
116
+ . split ( '\n' )
117
+ . map ( ( s ) => s . trim ( ) )
118
+ . slice ( 1 , - 1 )
119
+ . join ( '\n' ) ;
120
+ const keyDerBinary = fromBase64 ( keyDer ) . toBuffer ( ) ;
121
+ const [ type ] = types . entries ( ) . find ( ( [ , type ] ) => type === this . type ) ! ;
122
+ const wvd = buildWvd ( {
123
+ clientId : id ,
124
+ deviceType : type ,
125
+ securityLevel : this . securityLevel ,
126
+ privateKey : keyDerBinary ,
127
+ } ) ;
128
+ return wvd ;
129
+ } else if ( format === 'azot' ) {
130
+ const clientIdentification = this . id . toJSON ( ) ;
131
+ const privateKey = await this . exportKey ( ) ;
132
+ const payload = {
133
+ version : 1 ,
134
+ type : 'widevine-client' ,
135
+ data : {
136
+ clientIdentification,
137
+ privateKey : fromBuffer ( privateKey ) . toText ( ) ,
138
+ } ,
139
+ } ;
140
+ const data = JSON . stringify ( payload , null , 2 ) ;
141
+ return fromText ( data ) . toBuffer ( ) ;
142
+ } else {
143
+ throw new Error ( 'Unsupported format' ) ;
144
+ }
114
145
}
115
146
116
- async importKey ( pkcs1 : Uint8Array ) {
117
- const pkcs1pem = fromBuffer ( pkcs1 ) . toText ( ) ;
147
+ async importKey ( pkcs1 : Uint8Array | string ) {
148
+ const pkcs1pem =
149
+ typeof pkcs1 === 'string' ? pkcs1 : fromBuffer ( pkcs1 ) . toText ( ) ;
118
150
const pkcs8pem = toPKCS8 ( pkcs1pem ) ;
119
151
const pemContents = pkcs8pem . split ( '\n' ) . slice ( 1 , - 2 ) . join ( '\n' ) ;
120
152
const data = fromBase64 ( pemContents ) . toBuffer ( ) ;
0 commit comments