2010-10-15 30 views
31

Tôi cần mã hóa luồng bằng pgp bằng cách sử dụng nhà cung cấp bouncycastle. Tất cả các ví dụ tôi có thể tìm thấy về việc lấy một tập tin văn bản đơn giản và mã hóa rằng tuy nhiên tôi sẽ không có một tập tin và điều quan trọng là các văn bản đơn giản không bao giờ được ghi vào đĩa.Cách mã hóa chuỗi/luồng với pgp bouncycastle mà không bắt đầu bằng một tệp

Hầu hết các phương pháp tôi đã nhìn thấy đang sử dụng

PGPUtil.writeFileToLiteralData mà muốn bản rõ thông qua vào. Tôi thà Passin một byte [] hoặc một InputStream.

Ai đó có thể chỉ cho tôi một ví dụ mà

  • bắt đầu từ chuỗi/byte []/inputstream
  • encrypts nói chuỗi/byte [] để một outputStrem rằng tôi có thể viết vào một tập tin
  • giải mã từ một InputStream

Trong trường hợp bất cứ ai tình cờ khác trên này và muốn các giải pháp đầy đủ

package com.common.security.pgp; 

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.security.NoSuchProviderException; 
import java.security.SecureRandom; 
import java.security.Security; 
import java.util.Date; 
import java.util.Iterator; 

import org.bouncycastle.bcpg.ArmoredOutputStream; 
import org.bouncycastle.jce.provider.BouncyCastleProvider; 
import org.bouncycastle.openpgp.PGPCompressedData; 
import org.bouncycastle.openpgp.PGPCompressedDataGenerator; 
import org.bouncycastle.openpgp.PGPEncryptedData; 
import org.bouncycastle.openpgp.PGPEncryptedDataGenerator; 
import org.bouncycastle.openpgp.PGPEncryptedDataList; 
import org.bouncycastle.openpgp.PGPException; 
import org.bouncycastle.openpgp.PGPLiteralData; 
import org.bouncycastle.openpgp.PGPLiteralDataGenerator; 
import org.bouncycastle.openpgp.PGPObjectFactory; 
import org.bouncycastle.openpgp.PGPPrivateKey; 
import org.bouncycastle.openpgp.PGPPublicKey; 
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData; 
import org.bouncycastle.openpgp.PGPPublicKeyRing; 
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; 
import org.bouncycastle.openpgp.PGPSecretKey; 
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; 
import org.bouncycastle.openpgp.PGPUtil; 

/** 
* Simple routine to encrypt and decrypt using a Public and Private key with passphrase. This service 
* routine provides the basic PGP services between byte arrays. 
* 
*/ 
public class PgpEncryption { 


    private static PGPPrivateKey findSecretKey(
      PGPSecretKeyRingCollection pgpSec, long keyID, char[] pass) 
      throws PGPException, NoSuchProviderException { 
     PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID); 

     if (pgpSecKey == null) { 
      return null; 
     } 

     return pgpSecKey.extractPrivateKey(pass, "BC"); 
    } 

    /** 
    * decrypt the passed in message stream 
    * 
    * @param encrypted 
    *   The message to be decrypted. 
    * @param passPhrase 
    *   Pass phrase (key) 
    * 
    * @return Clear text as a byte array. I18N considerations are not handled 
    *   by this routine 
    * @exception IOException 
    * @exception PGPException 
    * @exception NoSuchProviderException 
    */ 
    public static byte[] decrypt(byte[] encrypted, InputStream keyIn, char[] password) 
      throws IOException, PGPException, NoSuchProviderException { 
     InputStream in = new ByteArrayInputStream(encrypted); 

     in = PGPUtil.getDecoderStream(in); 

     PGPObjectFactory pgpF = new PGPObjectFactory(in); 
     PGPEncryptedDataList enc = null; 
     Object o = pgpF.nextObject(); 

     // 
     // the first object might be a PGP marker packet. 
     // 
     if (o instanceof PGPEncryptedDataList) { 
      enc = (PGPEncryptedDataList) o; 
     } else { 
      enc = (PGPEncryptedDataList) pgpF.nextObject(); 
     } 



     // 
     // find the secret key 
     // 
     Iterator it = enc.getEncryptedDataObjects(); 
     PGPPrivateKey sKey = null; 
     PGPPublicKeyEncryptedData pbe = null; 
     PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(
       PGPUtil.getDecoderStream(keyIn)); 

     while (sKey == null && it.hasNext()) { 
      pbe = (PGPPublicKeyEncryptedData) it.next(); 

      sKey = findSecretKey(pgpSec, pbe.getKeyID(), password); 
     } 

     if (sKey == null) { 
      throw new IllegalArgumentException(
        "secret key for message not found."); 
     } 

     InputStream clear = pbe.getDataStream(sKey, "BC"); 



     PGPObjectFactory pgpFact = new PGPObjectFactory(clear); 

     PGPCompressedData cData = (PGPCompressedData) pgpFact.nextObject(); 

     pgpFact = new PGPObjectFactory(cData.getDataStream()); 

     PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject(); 

     InputStream unc = ld.getInputStream(); 

     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     int ch; 

     while ((ch = unc.read()) >= 0) { 
      out.write(ch); 

     } 

     byte[] returnBytes = out.toByteArray(); 
     out.close(); 
     return returnBytes; 
    } 

    /** 
    * Simple PGP encryptor between byte[]. 
    * 
    * @param clearData 
    *   The test to be encrypted 
    * @param passPhrase 
    *   The pass phrase (key). This method assumes that the key is a 
    *   simple pass phrase, and does not yet support RSA or more 
    *   sophisiticated keying. 
    * @param fileName 
    *   File name. This is used in the Literal Data Packet (tag 11) 
    *   which is really inly important if the data is to be related to 
    *   a file to be recovered later. Because this routine does not 
    *   know the source of the information, the caller can set 
    *   something here for file name use that will be carried. If this 
    *   routine is being used to encrypt SOAP MIME bodies, for 
    *   example, use the file name from the MIME type, if applicable. 
    *   Or anything else appropriate. 
    * 
    * @param armor 
    * 
    * @return encrypted data. 
    * @exception IOException 
    * @exception PGPException 
    * @exception NoSuchProviderException 
    */ 
    public static byte[] encrypt(byte[] clearData, PGPPublicKey encKey, 
      String fileName,boolean withIntegrityCheck, boolean armor) 
      throws IOException, PGPException, NoSuchProviderException { 
     if (fileName == null) { 
      fileName = PGPLiteralData.CONSOLE; 
     } 

     ByteArrayOutputStream encOut = new ByteArrayOutputStream(); 

     OutputStream out = encOut; 
     if (armor) { 
      out = new ArmoredOutputStream(out); 
     } 

     ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 

     PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(
       PGPCompressedDataGenerator.ZIP); 
     OutputStream cos = comData.open(bOut); // open it with the final 
     // destination 
     PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator(); 

     // we want to generate compressed data. This might be a user option 
     // later, 
     // in which case we would pass in bOut. 
     OutputStream pOut = lData.open(cos, // the compressed output stream 
       PGPLiteralData.BINARY, fileName, // "filename" to store 
       clearData.length, // length of clear data 
       new Date() // current time 
       ); 
     pOut.write(clearData); 

     lData.close(); 
     comData.close(); 

     PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(
       PGPEncryptedData.CAST5, withIntegrityCheck, new SecureRandom(), 
       "BC"); 

     cPk.addMethod(encKey); 

     byte[] bytes = bOut.toByteArray(); 

     OutputStream cOut = cPk.open(out, bytes.length); 

     cOut.write(bytes); // obtain the actual bytes from the compressed stream 

     cOut.close(); 

     out.close(); 

     return encOut.toByteArray(); 
    } 

    private static PGPPublicKey readPublicKey(InputStream in) 
      throws IOException, PGPException { 
     in = PGPUtil.getDecoderStream(in); 

     PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in); 

     // 
     // we just loop through the collection till we find a key suitable for 
     // encryption, in the real 
     // world you would probably want to be a bit smarter about this. 
     // 

     // 
     // iterate through the key rings. 
     // 
     Iterator rIt = pgpPub.getKeyRings(); 

     while (rIt.hasNext()) { 
      PGPPublicKeyRing kRing = (PGPPublicKeyRing) rIt.next(); 
      Iterator kIt = kRing.getPublicKeys(); 

      while (kIt.hasNext()) { 
       PGPPublicKey k = (PGPPublicKey) kIt.next(); 

       if (k.isEncryptionKey()) { 
        return k; 
       } 
      } 
     } 

     throw new IllegalArgumentException(
       "Can't find encryption key in key ring."); 
    } 

    public static byte[] getBytesFromFile(File file) throws IOException { 
     InputStream is = new FileInputStream(file); 

     // Get the size of the file 
     long length = file.length(); 

     if (length > Integer.MAX_VALUE) { 
      // File is too large 
     } 

     // Create the byte array to hold the data 
     byte[] bytes = new byte[(int)length]; 

     // Read in the bytes 
     int offset = 0; 
     int numRead = 0; 
     while (offset < bytes.length 
       && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) { 
      offset += numRead; 
     } 

     // Ensure all the bytes have been read in 
     if (offset < bytes.length) { 
      throw new IOException("Could not completely read file "+file.getName()); 
     } 

     // Close the input stream and return bytes 
     is.close(); 
     return bytes; 
    } 

    public static void main(String[] args) throws Exception { 
     Security.addProvider(new BouncyCastleProvider()); 


     byte[] original = "Hello world".getBytes(); 
     System.out.println("Starting PGP test"); 

     FileInputStream pubKey = new FileInputStream("/Users/me/pub.key"); 
     byte[] encrypted = encrypt(original, readPublicKey(pubKey), null, 
       true, true); 

     FileOutputStream dfis = new FileOutputStream("/Users/me/enc.asc"); 
     dfis.write(encrypted); 
     dfis.close(); 

     byte[] encFromFile = getBytesFromFile(new File("/Users/me/enc.asc")); 
     FileInputStream secKey = new FileInputStream("/Users/me/sec.key"); 

     System.out.println("\nencrypted data = '" + new String(encrypted) + "'"); 

     byte[] decrypted = decrypt(encFromFile, secKey, "passphrase".toCharArray()); 

     System.out.println("\ndecrypted data = '" + new String(decrypted) + "'"); 


    } 
} 

Trả lời

12

Nhìn vào source of PGPUtil bạn có thể xem những gì API để gọi khi làm việc với những con suối hoặc mảng trực tiếp:

public static void writeFileToLiteralData(OutputStream out, 
       char fileType, File file, byte[] buffer) throws IOException { 
    PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator(); 
    OutputStream pOut = lData.open(out, fileType, file.getName(), 
        new Date(file.lastModified()), buffer); 
    FileInputStream in = new FileInputStream(file); 
    byte[] buf = new byte[buffer.length]; 
    int len; 

    while ((len = in.read(buf)) > 0) { 
     pOut.write(buf, 0, len); 
    } 

    lData.close(); 
    in.close(); 
} 
+0

Yep Tôi thấy điều này chỉ sau khi công bố tuy nhiên tôi không muốn viết lại một cái gì đó mà ai đó bây giờ đã viết và chia sẻ :). Tôi sẽ viết nó nếu tôi phải nhưng tôi không phải trong toàn bộ cảnh tái chế bánh xe – dstarh

+1

Hóa ra có một ví dụ mảng byte sử dụng cụm từ mật khẩu thay vì pub/private nhưng tôi là abele để kết hợp ví dụ riêng tư công khai với byte mảng ví dụ và làm cho nó hoạt động. Một điều cần lưu ý là nếu không có tệp nào cả, bạn chỉ có thể sử dụng tên tệp PGPLiteralData.CONSOLE thay vì – dstarh

+0

Liên kết bị hỏng. Hãy kiểm tra. –

0

Mã của bạn là vô cùng hữu ích đối với tôi. Tôi đang làm việc trong Coldfusion (với Java) và cần mật khẩu, mã hóa chúng trong một tập tin nhập ngắn cho LDIFDE (được sử dụng trong Active Directory trên máy chủ khác) và tôi không bao giờ muốn mật khẩu chạm vào đĩa trong bản rõ. Tôi đã sửa đổi nó một chút để thêm hai hàm trừu tượng hóa trường hợp sử dụng phổ biến để mã hóa một chuỗi thành đĩa và giải mã từ đĩa. Cảm ơn bạn @ dstarh.

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.security.NoSuchProviderException; 
import java.security.SecureRandom; 
import java.security.Security; 
import java.util.Date; 
import java.util.Iterator; 

import org.bouncycastle.bcpg.ArmoredOutputStream; 
import org.bouncycastle.jce.provider.BouncyCastleProvider; 
import org.bouncycastle.openpgp.PGPCompressedData; 
import org.bouncycastle.openpgp.PGPCompressedDataGenerator; 
import org.bouncycastle.openpgp.PGPEncryptedData; 
import org.bouncycastle.openpgp.PGPEncryptedDataGenerator; 
import org.bouncycastle.openpgp.PGPEncryptedDataList; 
import org.bouncycastle.openpgp.PGPException; 
import org.bouncycastle.openpgp.PGPLiteralData; 
import org.bouncycastle.openpgp.PGPLiteralDataGenerator; 
import org.bouncycastle.openpgp.PGPObjectFactory; 
import org.bouncycastle.openpgp.PGPPrivateKey; 
import org.bouncycastle.openpgp.PGPPublicKey; 
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData; 
import org.bouncycastle.openpgp.PGPPublicKeyRing; 
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; 
import org.bouncycastle.openpgp.PGPSecretKey; 
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; 
import org.bouncycastle.openpgp.PGPUtil; 

/** 
* Simple routine to encrypt and decrypt using a Public and Private key with passphrase. This service 
* routine provides the basic PGP services between byte arrays. 
* 
*/ 
public class PgpEncryption { 

    public PgpEncryption() { 
     // Empty constructor 
    } 

    private static PGPPrivateKey findSecretKey(
      PGPSecretKeyRingCollection pgpSec, long keyID, char[] pass) 
      throws PGPException, NoSuchProviderException { 
     PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID); 

     if (pgpSecKey == null) { 
      return null; 
     } 

     return pgpSecKey.extractPrivateKey(pass, "BC"); 
    } 

    /** 
    * decrypt the passed in message stream 
    * 
    * @param encrypted 
    *   The message to be decrypted. 
    * @param passPhrase 
    *   Pass phrase (key) 
    * 
    * @return Clear text as a byte array. I18N considerations are not handled 
    *   by this routine 
    * @exception IOException 
    * @exception PGPException 
    * @exception NoSuchProviderException 
    */ 
    public static byte[] decrypt(byte[] encrypted, InputStream keyIn, char[] password) 
      throws IOException, PGPException, NoSuchProviderException { 
     InputStream in = new ByteArrayInputStream(encrypted); 

     in = PGPUtil.getDecoderStream(in); 

     PGPObjectFactory pgpF = new PGPObjectFactory(in); 
     PGPEncryptedDataList enc = null; 
     Object o = pgpF.nextObject(); 

     // 
     // the first object might be a PGP marker packet. 
     // 
     if (o instanceof PGPEncryptedDataList) { 
      enc = (PGPEncryptedDataList) o; 
     } else { 
      enc = (PGPEncryptedDataList) pgpF.nextObject(); 
     } 



     // 
     // find the secret key 
     // 
     Iterator it = enc.getEncryptedDataObjects(); 
     PGPPrivateKey sKey = null; 
     PGPPublicKeyEncryptedData pbe = null; 
     PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(
       PGPUtil.getDecoderStream(keyIn)); 

     while (sKey == null && it.hasNext()) { 
      pbe = (PGPPublicKeyEncryptedData) it.next(); 

      sKey = findSecretKey(pgpSec, pbe.getKeyID(), password); 
     } 

     if (sKey == null) { 
      throw new IllegalArgumentException(
        "secret key for message not found."); 
     } 

     InputStream clear = pbe.getDataStream(sKey, "BC"); 



     PGPObjectFactory pgpFact = new PGPObjectFactory(clear); 

     PGPCompressedData cData = (PGPCompressedData) pgpFact.nextObject(); 

     pgpFact = new PGPObjectFactory(cData.getDataStream()); 

     PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject(); 

     InputStream unc = ld.getInputStream(); 

     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     int ch; 

     while ((ch = unc.read()) >= 0) { 
      out.write(ch); 

     } 

     byte[] returnBytes = out.toByteArray(); 
     out.close(); 
     return returnBytes; 
    } 

    /** 
    * Simple PGP encryptor between byte[]. 
    * 
    * @param clearData 
    *   The test to be encrypted 
    * @param passPhrase 
    *   The pass phrase (key). This method assumes that the key is a 
    *   simple pass phrase, and does not yet support RSA or more 
    *   sophisiticated keying. 
    * @param fileName 
    *   File name. This is used in the Literal Data Packet (tag 11) 
    *   which is really inly important if the data is to be related to 
    *   a file to be recovered later. Because this routine does not 
    *   know the source of the information, the caller can set 
    *   something here for file name use that will be carried. If this 
    *   routine is being used to encrypt SOAP MIME bodies, for 
    *   example, use the file name from the MIME type, if applicable. 
    *   Or anything else appropriate. 
    * 
    * @param armor 
    * 
    * @return encrypted data. 
    * @exception IOException 
    * @exception PGPException 
    * @exception NoSuchProviderException 
    */ 
    public static byte[] encrypt(byte[] clearData, PGPPublicKey encKey, 
      String fileName,boolean withIntegrityCheck, boolean armor) 
      throws IOException, PGPException, NoSuchProviderException { 
     if (fileName == null) { 
      fileName = PGPLiteralData.CONSOLE; 
     } 

     ByteArrayOutputStream encOut = new ByteArrayOutputStream(); 

     OutputStream out = encOut; 
     if (armor) { 
      out = new ArmoredOutputStream(out); 
     } 

     ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 

     PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(
       PGPCompressedDataGenerator.ZIP); 
     OutputStream cos = comData.open(bOut); // open it with the final 
     // destination 
     PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator(); 

     // we want to generate compressed data. This might be a user option 
     // later, 
     // in which case we would pass in bOut. 
     OutputStream pOut = lData.open(cos, // the compressed output stream 
       PGPLiteralData.BINARY, fileName, // "filename" to store 
       clearData.length, // length of clear data 
       new Date() // current time 
       ); 
     pOut.write(clearData); 

     lData.close(); 
     comData.close(); 

     PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(
       PGPEncryptedData.CAST5, withIntegrityCheck, new SecureRandom(), 
       "BC"); 

     cPk.addMethod(encKey); 

     byte[] bytes = bOut.toByteArray(); 

     OutputStream cOut = cPk.open(out, bytes.length); 

     cOut.write(bytes); // obtain the actual bytes from the compressed stream 

     cOut.close(); 

     out.close(); 

     return encOut.toByteArray(); 
    } 

    private static PGPPublicKey readPublicKey(InputStream in) 
      throws IOException, PGPException { 
     in = PGPUtil.getDecoderStream(in); 

     PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in); 

     // 
     // we just loop through the collection till we find a key suitable for 
     // encryption, in the real 
     // world you would probably want to be a bit smarter about this. 
     // 

     // 
     // iterate through the key rings. 
     // 
     Iterator rIt = pgpPub.getKeyRings(); 

     while (rIt.hasNext()) { 
      PGPPublicKeyRing kRing = (PGPPublicKeyRing) rIt.next(); 
      Iterator kIt = kRing.getPublicKeys(); 

      while (kIt.hasNext()) { 
       PGPPublicKey k = (PGPPublicKey) kIt.next(); 

       if (k.isEncryptionKey()) { 
        return k; 
       } 
      } 
     } 

     throw new IllegalArgumentException(
       "Can't find encryption key in key ring."); 
    } 

    public static byte[] getBytesFromFile(File file) throws IOException { 
     InputStream is = new FileInputStream(file); 

     // Get the size of the file 
     long length = file.length(); 

     if (length > Integer.MAX_VALUE) { 
      // File is too large 
     } 

     // Create the byte array to hold the data 
     byte[] bytes = new byte[(int)length]; 

     // Read in the bytes 
     int offset = 0; 
     int numRead = 0; 
     while (offset < bytes.length 
       && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) { 
      offset += numRead; 
     } 

     // Ensure all the bytes have been read in 
     if (offset < bytes.length) { 
      throw new IOException("Could not completely read file "+file.getName()); 
     } 

     // Close the input stream and return bytes 
     is.close(); 
     return bytes; 
    } 

    public static String encryptToFile(String inputStr, String keyFile, String outFile) throws Exception { 
     Security.addProvider(new BouncyCastleProvider()); 

     byte[] original = inputStr.getBytes(); 

     FileInputStream pubKey = new FileInputStream(keyFile); 
     byte[] encrypted = encrypt(original, readPublicKey(pubKey), null, 
       true, true); 

     FileOutputStream dfis = new FileOutputStream(outFile); 
     dfis.write(encrypted); 
     dfis.close(); 

     return new String(encrypted); 
    } 

    public static String decryptFromFile(String passphrase, String keyFile, String inputFile) throws Exception { 
     Security.addProvider(new BouncyCastleProvider()); 

     byte[] encFromFile = getBytesFromFile(new File(inputFile)); 
     FileInputStream secKey = new FileInputStream(keyFile); 

     byte[] decrypted = decrypt(encFromFile, secKey, passphrase.toCharArray()); 

     return new String(decrypted); 
    } 

    public static void main(String[] args) throws Exception { 
     String encrypted = encryptToFile("Hello world","pub.asc","enc.asc"); 
     System.out.println("\nencrypted data = '" + new String(encrypted) + "'"); 

     String decrypted = decryptFromFile("open sesame", "secret.asc", "enc.asc"); 
     System.out.println("\ndecrypted data = '" + decrypted + "'"); 

    } 
} 
+2

Đây không thực sự là câu trả lời cho câu hỏi của tôi, cũng không thực sự phù hợp với các nguyên tắc SO. Câu hỏi cụ thể là KHÔNG viết vào một tập tin và ví dụ của bạn thêm khả năng ghi vào và từ một tập tin, trong đó có rất nhiều ví dụ ở nơi khác. Dod dường như không phải là một ví dụ kinh điển về cách làm điều đó chỉ trong bộ nhớ. – dstarh

2

Tìm thấy tại grepcode repository - payneteasy superfly sources

private static void writeBytesToLiteralData(OutputStream out, 
    char fileType, String name, byte[] bytes) throws IOException { 
     PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator(); 
     OutputStream pOut = lData.open(out, fileType, name,bytes.length, new Date()); 
     pOut.write(bytes); 
} 
Các vấn đề liên quan