福昕阅读器drm加密解密总结
drm是数字版权保护的一种方式,前一段时间在做四川文轩数字图书馆项目的时候用到了相关的知识,感觉这东西对于一些在线阅读和视频播放还是有很大用处的。
对于其工作原理我也很好奇,先摘抄度娘的内容如下,当然你也可以直接访问度娘:http://baike.baidu.com/view/47310.htm?fr=aladdin
DRM技术的工作原理是,首先建立数字节目授权中心。编码压缩后的数字节目内容,可以利用密钥(Key)进行加密保护(lock),加密的数字节目头部存放着KeyID和节目授权中心的URL。用户在点播时,根据节目头部的KeyID和URL信息,就可以通过数字节目授权中心的验证授权后送出相关的密钥解密(unlock),节目方可播放。
需要保护的节目被加密,即使被用户下载保存,没有得到数字节目授权中心的验证授权也无法播放,从而严密地保护了节目的版权。
密钥一般有两把,一把公钥(public key),一把私钥(private key)。公钥用于加密节目内容本身,私钥用于解密节目,私钥还可以防止当节目头部有被改动或破坏的情况,利用密钥就可以判断出来,从而阻止节目被非法使用。 上述这种加密的方法,有一个明显的缺陷,就是当解密的密钥在发送给用户时,一旦被黑客获得密钥,即可方便解密节目,从而不能真正确保节目内容提供商的实际版权利益。另一种更加安全的加密方法是使用三把密钥,即把密钥分成两把,一把存放在用户的Pc机上,另一把放在验证站(access ticket)。要解密数字节目,必须同时具备这两把密钥,方能解开数字节目。
毫无疑问,加密保护技术在开发电子商务系统中正起着重要的防盗版作用。比如,在互联网上传输音乐或视频节目等内容,这些内容很容易被拷贝复制。为了避免这些风险,节目内容在互联网上传输过程中一般都要经过加密保护。也就是说,收到加密的数字节目的人必须有一把密钥(key)才能打开数字节目并播放收看。因此,传送密钥的工作必须紧跟在加密节目传输之后。
市场上比较多应用的是微软的 DRM 技术。
系统原理
系统会将密钥标识和许可证颁发机构地址写入打包加密后的内容的头部,并且使用另一对密钥。
通过椭圆曲线加密算法对头部信息进行签名,防止头部信息被非法修改。
这个密钥散列的前12字节将用作生成加密过程中使用的密钥。
这12个字节将作为一个密钥,通过RC4算法加密一个全零的64字节串,得到一个64字节的加密结果。
具体运算过程是,32位数据与6个32位字的的密钥的第一节字节相乘,然后除以4294967296,取其余数,并交换结果的高16位和低16位,然后再与6个32位字的的密钥的第二节字节相乘,然后除以4294967296取其余数,并交换结果的高16位和低16位,然后再与6个32位字的的密钥的第三节字节相乘,然后除以4294967296取其余数,并交换结果的高16位和低16位,然后再与6个字节的密钥的第四节字节相乘,然后除以4294967296取其余数,并交换结果的高16位和低16位,然后再与6个32位字的的密钥的第一节字节相乘,然后除以4294967296取其余数,并交换结果的高16位和低16位,然后再加上6个32位字的密钥,然后除以4294967296取其余数,上述过程定义为函数f(x),设一个64位状态值,并设初值为零。
说了太多的废话,这玩意儿到底怎么用还没说,下面来点干货,上代码
1 /** 2 * 文件名 BaseFoac.java 3 * 包含类名列表 com.issmobile.numlibrary.tool 4 * 版本信息 版本号 5 * 创建日期 2014年7月15日 6 * 版权声明 7 */ 8 9 package com.issmobile.numlibrary.tool; 10 11 import java.io.BufferedReader; 12 import java.io.InputStreamReader; 13 import java.net.InetAddress; 14 15 import org.apache.http.HttpEntity; 16 import org.apache.http.HttpResponse; 17 import org.apache.http.client.CookieStore; 18 import org.apache.http.client.methods.HttpPost; 19 import org.apache.http.entity.StringEntity; 20 import org.apache.http.impl.client.AbstractHttpClient; 21 import org.apache.http.impl.client.DefaultHttpClient; 22 import org.apache.http.params.CoreConnectionPNames; 23 24 import android.util.Log; 25 26 import com.foxit.general.BufferFileRead; 27 import com.foxit.general.DrmNative; 28 import com.foxit.general.PdfBaseDef; 29 import com.foxit.general.PdfDocNative; 30 import com.foxit.general.PdfDrmNative; 31 import com.foxit.general.ObjectRef; 32 import com.foxit.general.PdfSecurityNative; 33 import com.foxit.general.RsaKey; 34 import com.foxit.general.RtBaseDef; 35 import com.foxit.general.RtNative; 36 37 /** 38 * 类名 39 * @author 王洪贺<br/> 40 * 实现的主要功能。 41 * 创建日期 2014年7月15日 42 */ 43 44 public class BaseFoac { 45 46 protected ObjectRef m_encryptParams = null; 47 private CookieStore m_cookieStore = null; 48 private byte[] m_decoderPubKey = null; 49 50 /**用户名*/ 51 private String mUserName; 52 /**密码*/ 53 private String mPassword; 54 /**密码*/ 55 private String mDevSN; 56 57 private String m_host = null; 58 private String m_port = null; 59 private String m_object = null; 60 private ObjectRef security = null; 61 private RsaKey m_rsaKey = null; 62 /**文件本地地址*/ 63 private String drmfile = null; 64 private DefaultHttpClient httpClient = null;//new DefaultHttpClient(); 65 private String m_sessionID = null; 66 67 /** 68 * 获取信封的时候初始化,需要用户名密码 69 * */ 70 public BaseFoac(String mUserName, String mPassword, String drmfile) { 71 this.mUserName = "ElibUser." + mUserName; 72 this.mPassword = mPassword; 73 this.mDevSN = mPassword; 74 this.drmfile = drmfile; 75 } 76 77 /** 78 * 解密文件的时候初始化 79 * */ 80 public BaseFoac() { 81 } 82 83 public void setDRMFileName(String filename) { 84 drmfile = filename; 85 } 86 87 public boolean isDocWrapper(ObjectRef document) { 88 if (!PdfDrmNative.isDocWrapper(document)) 89 return false; 90 return true; 91 } 92 93 public boolean isFoxitDRM(ObjectRef document) { 94 if (!PdfDrmNative.isDocWrapper(document)) 95 return false; 96 97 m_encryptParams = PdfDrmNative.getEncryptParams(document); 98 99 if (m_encryptParams == null) 100 return false; 101 102 return true; 103 } 104 105 protected String getServiceURL() { 106 //TODO 获取到书籍中验证drm的网址,由于目前服务器不可用,返回默认地址,正式版修改回来 107 // return PdfDrmNative.getEncryptParamsItemString(m_encryptParams, 108 // PdfBaseDef.ENCRYPTPARAMS_SERVICEURL); 109 return URLConstants.licenseURL; 110 } 111 112 /** 113 * 解析网址 114 */ 115 protected void parseURL(String serviceUrl) { 116 if (serviceUrl == null) 117 return; 118 int hostIndex = serviceUrl.indexOf("://"); 119 String tmp = serviceUrl.substring(hostIndex + 3); 120 int objIndex = tmp.indexOf("/"); 121 int portIndex = tmp.indexOf(":"); 122 if (portIndex < 0) { 123 m_port = "80"; 124 m_host = tmp.substring(0, objIndex); 125 } else { 126 m_port = tmp.substring(portIndex + 1, objIndex); 127 m_host = tmp.substring(0, portIndex); 128 } 129 m_object = tmp.substring(objIndex + 1); 130 } 131 132 /** 133 * 获取开始的请求信息 134 */ 135 protected String getSessionBeginRequest(String sessionID) { 136 ObjectRef foac = DrmNative.createFoac(true); 137 if (foac == null) 138 return null; 139 140 DrmNative.setFoacSessionID(foac, sessionID); 141 142 ObjectRef category = DrmNative.getFoacDataCategory(foac); 143 if (category == null) { 144 DrmNative.deleteFoac(foac); 145 return null; 146 } 147 148 DrmNative.setFoacRequestID(foac, "SessionBegin"); 149 150 ObjectRef subCategory = DrmNative.addSubCategory(category, "FlowCode", true); 151 String flowCode = PdfDrmNative.getEncryptParamsItemString(m_encryptParams, 152 PdfBaseDef.ENCRYPTPARAMS_FLOWCODE); 153 DrmNative.setCategoryAttribute(subCategory, "Value", flowCode); 154 155 String request = DrmNative.saveFoac(foac); 156 DrmNative.deleteFoac(foac); 157 return "XmlContent=" + request; 158 } 159 160 /** 161 * 发送请求信息并返回接受到的数据,需访问网络 162 */ 163 protected String sendAndReceive(String bsSend) { 164 String result = null; 165 try { 166 httpClient = new DefaultHttpClient(); 167 String temp = bsSend.replace("&", "%26"); 168 temp = temp.replace("+", "%2B"); 169 InetAddress addr = InetAddress.getByName(m_host); 170 171 String url; 172 if (addr.toString().substring(1).indexOf("/") != -1) 173 url = "http://" + m_host + ":" + m_port + "/" + m_object; 174 else 175 url = "http://" + m_host + ":" + m_port + "/" + m_object; 176 HttpPost httpPost = new HttpPost(url); 177 HttpEntity entity = new StringEntity(temp); 178 httpPost.setEntity(entity); 179 180 httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); 181 182 // if (m_cookieStore != null) 183 httpClient.setCookieStore(m_cookieStore); 184 185 httpClient.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 300000); 186 httpClient.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 300000); 187 188 HttpResponse httpResponse = httpClient.execute(httpPost); 189 int status = httpResponse.getStatusLine().getStatusCode(); 190 long len = httpResponse.getEntity().getContentLength(); 191 192 StringBuilder builder = new StringBuilder(); 193 BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse 194 .getEntity().getContent())); 195 for (String s = reader.readLine(); s != null; s = reader.readLine()) { 196 builder.append(s); 197 } 198 result = builder.toString(); 199 m_cookieStore = ((AbstractHttpClient) httpClient).getCookieStore(); 200 201 if (result.indexOf("xml") == -1) 202 return null; 203 204 } catch (Exception e) { 205 e.printStackTrace(); 206 } 207 return result; 208 } 209 210 /** 211 * 解析收到的信息 212 */ 213 protected void parseSessionBeginRecieve(String receive) { 214 ObjectRef foac = DrmNative.loadFoac(receive.getBytes()); 215 if (foac == null) 216 return; 217 218 String state = DrmNative.getFoacAnswerState(foac); 219 if (state.indexOf("1") > -1) { 220 ObjectRef category = DrmNative.getFoacDataCategory(foac); 221 222 //Pubkey 223 int iCount = DrmNative.countSubCategories(category, "ServerPubKey"); 224 if (iCount == 0) { 225 DrmNative.deleteFoac(foac); 226 return; 227 } 228 ObjectRef subCategory = DrmNative.getSubCategory(category, "ServerPubKey", 0); 229 String bsPubKey = DrmNative.getCategoryAttributeValue(subCategory, "Value"); 230 231 ObjectRef sessionID = DrmNative.getSubCategory(category, "SessionID", 0); 232 m_sessionID = DrmNative.getCategoryAttributeValue(sessionID, "Value"); 233 234 // m_decoderPubKey = Base64.decode(bsPubKey, Base64.DEFAULT); 235 m_decoderPubKey = RtNative.base64Decode(bsPubKey.getBytes(), 0, bsPubKey.length()); 236 } 237 DrmNative.deleteFoac(foac); 238 } 239 240 /** 241 * 加密字符串 242 */ 243 protected String EncryptString(String str) { 244 byte[] data = DrmNative.pkiRsaEncrypt(str, m_decoderPubKey); 245 //return Base64.encodeToString(data, Base64.DEFAULT); 246 return RtNative.base64EncodeToString(data, 0, data.length); 247 } 248 249 /** 250 * 获取检查账户的请求信息 251 */ 252 protected String GetCheckAccountRequest(String sessionID) { 253 String fileID = PdfDrmNative.getEncryptParamsItemString(m_encryptParams, 254 PdfBaseDef.ENCRYPTPARAMS_FILEID); 255 String strFileID = EncryptString(fileID); 256 257 String order = PdfDrmNative.getEncryptParamsItemString(m_encryptParams, 258 PdfBaseDef.ENCRYPTPARAMS_ORDER); 259 String strOrder = EncryptString(order); 260 261 String account = EncryptString(mUserName); 262 String password = EncryptString(mPassword); 263 264 ObjectRef foac = DrmNative.createFoac(true); 265 DrmNative.setFoacSessionID(foac, sessionID); 266 267 DrmNative.setFoacRequestID(foac, "AuthAccount"); 268 269 ObjectRef category = DrmNative.getFoacDataCategory(foac); 270 if (category == null) { 271 DrmNative.deleteFoac(foac); 272 return null; 273 } 274 275 ObjectRef subCategory = DrmNative.addSubCategory(category, "EncryptAccount", true); 276 DrmNative.setCategoryAttribute(subCategory, "Value", account); 277 278 subCategory = DrmNative.addSubCategory(category, "EncryptPassword", true); 279 DrmNative.setCategoryAttribute(subCategory, "Value", password); 280 281 subCategory = DrmNative.addSubCategory(category, "EncryptOrderID", true); 282 DrmNative.setCategoryAttribute(subCategory, "Value", strOrder); 283 284 subCategory = DrmNative.addSubCategory(category, "EncryptFileID", true); 285 DrmNative.setCategoryAttribute(subCategory, "Value", strFileID); 286 287 String request = DrmNative.saveFoac(foac); 288 289 DrmNative.deleteFoac(foac); 290 291 return "XmlContent=" + request; 292 } 293 294 /** 295 * 解析收到账户认证的信息 296 */ 297 protected boolean ParseCheckAccountRequest(String receive) { 298 ObjectRef foac = DrmNative.loadFoac(receive.getBytes()); 299 if (foac == null) 300 return false; 301 302 boolean bRet = false; 303 304 ///foac verify 305 String bsState = DrmNative.getFoacAnswerState(foac); 306 if (bsState.equals("1")) { 307 ObjectRef category = DrmNative.getFoacDataCategory(foac); 308 309 int iCount = DrmNative.countSubCategories(category, "Result"); 310 if (iCount == 0) { 311 DrmNative.deleteFoac(foac); 312 return false; 313 } 314 ObjectRef subCategory = DrmNative.getSubCategory(category, "Result", 0); 315 String result = DrmNative.getCategoryAttributeValue(subCategory, "Value"); 316 bRet = result.equals("1"); 317 } 318 DrmNative.deleteFoac(foac); 319 return bRet; 320 } 321 322 /** 323 * 获取信封请求信息 324 */ 325 public String GetEnvelopRequest(String sessionID) { 326 String fileID = PdfDrmNative.getEncryptParamsItemString(m_encryptParams, 327 PdfBaseDef.ENCRYPTPARAMS_FILEID); 328 String strFileID = EncryptString(fileID); 329 330 String order = PdfDrmNative.getEncryptParamsItemString(m_encryptParams, 331 PdfBaseDef.ENCRYPTPARAMS_ORDER); 332 String strOrder = order;//EncryptString(order); 333 334 String userName = mUserName;//EncryptString(m_userName); 335 String password = EncryptString(mPassword); 336 String devSn = EncryptString(mDevSN); 337 338 byte[] seed = { 339 'F', 'o', 'x', 'i', 't', 'A', 'n', 'd', 'r', 'o', 'i', 'd' 340 }; 341 342 m_rsaKey = DrmNative.createRsaKey(1024, seed, null); 343 344 if (m_rsaKey == null) 345 return null; 346 347 String strClientPubKey = RtNative.base64EncodeToString(m_rsaKey.publicKey, 0, 348 m_rsaKey.publicKey.length); 349 // String strClientPubKey = Base64.encodeToString(clientPubKey, Base64.DEFAULT); 350 351 ObjectRef foac = DrmNative.createFoac(true); 352 DrmNative.setFoacSessionID(foac, sessionID); 353 354 DrmNative.setFoacRequestID(foac, "GetEnvelop"); 355 356 ObjectRef category = DrmNative.getFoacDataCategory(foac); 357 if (category == null) { 358 DrmNative.deleteFoac(foac); 359 return null; 360 } 361 362 ObjectRef subCategory = DrmNative.addSubCategory(category, "OrderID", true); 363 DrmNative.setCategoryAttribute(subCategory, "Value", strOrder); 364 365 subCategory = DrmNative.addSubCategory(category, "EncryptFileID", true); 366 DrmNative.setCategoryAttribute(subCategory, "Value", strFileID); 367 368 subCategory = DrmNative.addSubCategory(category, "ClientPubKey", true); 369 DrmNative.setCategoryAttribute(subCategory, "Value", strClientPubKey); 370 371 subCategory = DrmNative.addSubCategory(category, "Usermail", true); 372 DrmNative.setCategoryAttribute(subCategory, "Value", userName); 373 374 subCategory = DrmNative.addSubCategory(category, "EncryptPassword", true); 375 DrmNative.setCategoryAttribute(subCategory, "Value", password); 376 377 subCategory = DrmNative.addSubCategory(category, "EncryptDeviceSN", true); 378 DrmNative.setCategoryAttribute(subCategory, "Value", devSn); 379 380 String request = DrmNative.saveFoac(foac); 381 382 DrmNative.deleteFoac(foac); 383 384 return "XmlContent=" + request; 385 } 386 387 /** 388 * 解析收到的信封信息 389 */ 390 public boolean parseEnvelopRequest(ObjectRef document, String receive) { 391 392 BufferFileRead bufReader = new BufferFileRead(receive.getBytes(), 0); 393 ObjectRef envelope = DrmNative.loadEnvelope(bufReader); 394 byte[] key = DrmNative.getEnvelopeKey(envelope); 395 396 String algorithm = DrmNative.getEnvelopeAlgorithm(envelope); 397 byte[] deKey = DrmNative.pkiRsaDecrypt(key, m_rsaKey.privateKey); 398 399 security = new ObjectRef(); 400 String filter = "FoxitSTD"; 401 int ret = PdfSecurityNative.createFoxitDRMSecurity(filter, 402 algorithm.equals("FOXIT_ENCRYPT2") ? RtBaseDef.CIPHER_AES : RtBaseDef.CIPHER_RC4, 403 deKey, security); 404 if (ret != RtBaseDef.ERR_SUCCESS) 405 return false; 406 407 int offset = PdfDrmNative.getDocWrapperOffset(document); 408 boolean flag = PdfSecurityNative.verifyFoxitDRMSecurity(security); 409 410 ret = PdfDocNative.closeDoc(document); 411 if (ret != RtBaseDef.ERR_SUCCESS) 412 return false; 413 414 ret = PdfDocNative.loadDoc(drmfile, 0, offset, document); 415 if (ret != RtBaseDef.ERR_SUCCESS) 416 return false; 417 418 return true; 419 } 420 421 /** 422 * 解密文件 423 */ 424 public boolean decrypt(ObjectRef document) { 425 if (document == null) 426 return false; 427 428 String serviceUrl = getServiceURL(); 429 if (serviceUrl == null) 430 return false; 431 parseURL(serviceUrl); 432 System.out.println("URL ==" + serviceUrl); 433 434 String sessionID = "6F9629FF-8A86-D011-B42D-00C04FC964FF"; 435 String send = getSessionBeginRequest(sessionID); 436 if (send == null) 437 return false; 438 String receive = sendAndReceive(send); 439 if (receive == null) 440 return false; 441 parseSessionBeginRecieve(receive); 442 443 String checkAccount = GetCheckAccountRequest(sessionID); 444 if (checkAccount == null) 445 return false; 446 receive = sendAndReceive(checkAccount); 447 if (receive == null) 448 return false; 449 if (!ParseCheckAccountRequest(receive)) 450 return false; 451 452 String envelope = GetEnvelopRequest(sessionID); 453 if (envelope == null) 454 return false; 455 receive = sendAndReceive(envelope); 456 if (receive == null) 457 return false; 458 459 return parseEnvelopRequest(document, receive); 460 } 461 462 /** 463 * 获取信封 464 * @author honghe 465 */ 466 public String getEnvelop(ObjectRef document) { 467 if (document == null) 468 return null; 469 470 String serviceUrl = getServiceURL(); 471 if (serviceUrl == null) 472 return null; 473 parseURL(serviceUrl); 474 System.out.println("URL ==" + serviceUrl); 475 476 String sessionID = "6F9629FF-8A86-D011-B42D-00C04FC964FF"; 477 String send = getSessionBeginRequest(sessionID); 478 if (send == null) 479 return null; 480 String receive = sendAndReceive(send); 481 if (receive == null) 482 return null; 483 parseSessionBeginRecieve(receive); 484 485 String checkAccount = GetCheckAccountRequest(sessionID); 486 if (checkAccount == null) 487 return null; 488 receive = sendAndReceive(checkAccount); 489 if (receive == null) 490 return null; 491 if (!ParseCheckAccountRequest(receive)) 492 return null; 493 494 String envelope = GetEnvelopRequest(sessionID); 495 if (envelope == null) 496 return null; 497 receive = sendAndReceive(envelope); 498 if (receive == null) 499 return null; 500 501 return receive; 502 } 503 504 /** 505 * 根据信封信息解密文档 506 * @author honghe 507 */ 508 public boolean decryptDoc(ObjectRef document, String receive) { 509 BufferFileRead bufReader = new BufferFileRead(receive.getBytes(), 0); 510 ObjectRef envelope = DrmNative.loadEnvelope(bufReader); 511 byte[] key = DrmNative.getEnvelopeKey(envelope); 512 String algorithm = DrmNative.getEnvelopeAlgorithm(envelope); 513 byte[] seed = { 514 'F', 'o', 'x', 'i', 't', 'A', 'n', 'd', 'r', 'o', 'i', 'd' 515 }; 516 m_rsaKey = DrmNative.createRsaKey(1024, seed, null); 517 byte[] deKey = DrmNative.pkiRsaDecrypt(key, m_rsaKey.privateKey); 518 519 security = new ObjectRef(); 520 String filter = "FoxitSTD"; 521 int ret = PdfSecurityNative.createFoxitDRMSecurity(filter, 522 algorithm.equals("FOXIT_ENCRYPT2") ? RtBaseDef.CIPHER_AES : RtBaseDef.CIPHER_RC4, 523 deKey, security); 524 if (ret != RtBaseDef.ERR_SUCCESS) 525 return false; 526 527 int offset = PdfDrmNative.getDocWrapperOffset(document); 528 boolean flag = PdfSecurityNative.verifyFoxitDRMSecurity(security); 529 530 ret = PdfDocNative.closeDoc(document); 531 if (ret != RtBaseDef.ERR_SUCCESS) 532 return false; 533 534 ret = PdfDocNative.loadDoc(drmfile, 0, offset, document); 535 if (ret != RtBaseDef.ERR_SUCCESS) 536 return false; 537 538 return true; 539 } 540 541 public void destroy() { 542 int ret = RtBaseDef.ERR_ERROR; 543 if (m_encryptParams != null) 544 ret = PdfDrmNative.releaseEncryptParams(m_encryptParams); 545 if (security != null) 546 ret = PdfSecurityNative.destroySecurity(security); 547 548 } 549 550 }
简单的说一下调用的过程:
1.首先用客户端下载一本经过drm加密的书籍(加密的过程是文轩那边已经加密好的了)
2.下载完后根据书籍中的drm地址和加密信息以及用户的用户名和密码获取信封(按照福昕提供的api是在阅读的时候在线联网解密的,但客户要求可以离线阅读,因此下载书的时候要先取得解密用的信封)
获取信封的调用方法
1 if(finished) { 2 FoxitRAMManager.getInstance(); 3 ObjectRef document = new ObjectRef(); 4 int result = PdfDocNative.loadDoc(book.loc, null, document); 5 if (result != RtBaseDef.ERR_SUCCESS) { 6 throw new Exception("load drm fail!"); 7 } 8 User user = AppContext.getInstance().getUserModel().user; 9 BaseFoac baseFoac = new BaseFoac(user.uName, user.pwd, book.loc); 10 if (baseFoac.isFoxitDRM(document)) { 11 baseFoac.setDRMFileName(book.loc); 12 String envelop = baseFoac.getEnvelop(document); 13 if (envelop != null) { 14 book.receive = envelop; 15 } 16 else { 17 throw new Exception("get envelop fail!"); 18 } 19 } 20 // baseFoac.destroy(); 21 PdfDocNative.closeDoc(document); 22 }
3.将获取的信封根据书籍对应的信息保存到数据库中,一本书一个用来解密的信封。
4.用户打开书籍的时候获取该书籍存储于数据库中的信封,用信封对书籍进行解密,用户就可以看到该书籍了。
1 FoxitRAMManager.getInstance(); 2 document = new ObjectRef(); 3 int result = PdfDocNative.loadDoc(filePath, null, document); 4 if (result != RtBaseDef.ERR_SUCCESS) 5 return false; 6 // 根据得到的信封解密书籍 7 mBaseFoac = new BaseFoac(); 8 if (mBaseFoac.isDocWrapper(document)) { 9 mBaseFoac.setDRMFileName(filePath); 10 if (!mBaseFoac.decryptDoc(document, receive)) { 11 return false; 12 } 13 } else { 14 return false; 15 }
这样做的好处是该用户下载的书籍用其他的阅读器是无法打开的,而且解密的信封也是跟用户和服务器相关的,其他人或者是不联网验证也是无法查看传送的书籍的,有效的保护了数字版权。
代码已上传github。
地址为:https://github.com/dongweiq/study/tree/master/pdf_drm
代码中appid和password已删除,此外你只有加入jar包和so文件才可以运行。
我的github地址:https://github.com/dongweiq/study
欢迎关注,欢迎star o(∩_∩)o 。有什么问题请邮箱联系 dongweiqmail@gmail.com qq714094450