2017-12-07 15 views
0

Rijndael .Net 암호화 파일과 .Net RSA XML Key가 Java에서 해독되도록 요청되었습니다.Rijndael을 사용하여 .Net에서 암호화 된 파일의 암호를 해독하는 중 오류가 발생했습니다.

나에게 제공되는 키는 256 비트입니다.

RSA XML 파일을 구문 분석하고 공개 키를 Java로 생성했습니다. 생성 된 키를 사용하여 암호 해독을 시도했지만 예외가 발생했습니다. Illegal Key Size, 제 Java 코드에서 잘못된 것 같습니다.

내 코드에 문제가 있는지 확인할 수있는 사람이 있습니까?

닷넷 암호화 코드 :

public static void EncryptFile(string fileIn, string fileOut, 
            string publicKeyName, string publicKeyFile) 
    { 
     try 
     { 
      // Read the public key from key file 
      StreamReader sr = new StreamReader(publicKeyFile); 
      string strKeyText = sr.ReadToEnd(); 
      sr.Close(); 

      //Initialize Key container and Crypto service provider 
      RSACryptoServiceProvider rsa; 
      CspParameters cspp = new CspParameters(); 
      cspp.KeyContainerName = publicKeyName; 
      rsa = new RSACryptoServiceProvider(cspp); 
      rsa.FromXmlString(strKeyText); 
      rsa.PersistKeyInCsp = true; 

      // Create instance of Rijndael for 
      // symetric encryption of the data. 
      RijndaelManaged alg = new RijndaelManaged(); 
      // Key size is set to 256 for strong encryption 
      alg.KeySize = 256; 
      alg.BlockSize = 256; 
      // Cipher Mode is set to CBC to process the file in chunks 
      alg.Mode = CipherMode.CBC; 
      // Set padding mode to process the last block of the file 
      alg.Padding = PaddingMode.ISO10126; 

      ICryptoTransform transform = alg.CreateEncryptor(); 

      // Use RSACryptoServiceProvider to 
      // enrypt the Rijndael key. 
      byte[] KeyEncrypted = rsa.Encrypt(alg.Key, false); 

      // Create byte arrays to contain 
      // the length values of the key and IV. 
      int intKeyLength = KeyEncrypted.Length; 
      byte[] LenK = BitConverter.GetBytes(intKeyLength); 
      int intIVLength = alg.IV.Length; 
      byte[] LenIV = BitConverter.GetBytes(intIVLength); 


      using (FileStream fsOut = new FileStream(fileOut, FileMode.Create)) 
      { 
       // Write the following to the FileStream 
       // for the encrypted file (fsOut): 
       // - length of the key 
       // - length of the IV 
       // - ecrypted key 
       // - the IV 
       // - the encrypted cipher content 
       fsOut.Write(LenK, 0, 4); 
       fsOut.Write(LenIV, 0, 4); 
       fsOut.Write(KeyEncrypted, 0, intKeyLength); 
       fsOut.Write(alg.IV, 0, intIVLength); 

       // Now write the cipher text using 
       // a CryptoStream for encrypting. 
       using (CryptoStream cs = new CryptoStream(fsOut, transform, CryptoStreamMode.Write)) 
       { 
        // intBlockSizeBytes can be any arbitrary size. 
        int intBlockSizeBytes = alg.BlockSize/8; 
        byte[] DataBytes = new byte[intBlockSizeBytes]; 
        int intBytesRead = 0; 

        using (FileStream fsIn = new FileStream(fileIn, FileMode.Open)) 
        { 
         // By encrypting a chunk at 
         // a time, you can save memory 
         // and accommodate large files. 
         int intCount; 
         int intOffset = 0; 

         do 
         { 
          // if last block size is less than encryption chunk size 
          // use the last block size and padding character is used 
          // for remaining bytes 
          if (intBlockSizeBytes > (fsIn.Length - fsIn.Position)) 
          { 
           intBlockSizeBytes = ((int)(fsIn.Length - fsIn.Position)); 
           DataBytes = new byte[intBlockSizeBytes]; 
          } 
          // read data bytes 
          intCount = fsIn.Read(DataBytes, 0, intBlockSizeBytes); 
          intOffset += intCount; 
          // write it into crypto stream 
          cs.Write(DataBytes, 0, intCount); 
          intBytesRead += intBlockSizeBytes; 
         } while (intCount > 0); 
         // close input file 
         fsIn.Close(); 
        } 
        // close crypto stream 
        cs.FlushFinalBlock(); 
        cs.Close(); 
       } 
       // close output file 
       fsOut.Close(); 
      } 
     } 
     catch 
     { 
      throw; 
     } 
    } 

자바 코드 나는 그것을 해독하는 데 쓴 :

byte[] expBytes = Base64.decodeBase64(pkey.getExponentEle().trim()); 
    byte[] modBytes = Base64.decodeBase64(pkey.getModulusEle().trim()); 
    byte[] dBytes = Base64.decodeBase64(pkey.getdEle().trim()); 

    BigInteger modules = new BigInteger(1, modBytes); 
    BigInteger exponent = new BigInteger(1, expBytes); 
    BigInteger d = new BigInteger(1, dBytes); 

    KeyFactory factory = KeyFactory.getInstance("RSA"); 
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

    RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(modules, exponent); 
    PublicKey pubKey = factory.generatePublic(pubSpec); 

    final byte[] keyData = Arrays.copyOf(pubKey.getEncoded(), 256 
      /Byte.SIZE); 
     final byte[] ivBytes = Arrays.copyOf(keyData, cipher.getBlockSize()); 
     AlgorithmParameterSpec paramSpec = new IvParameterSpec(ivBytes); 

     cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyData, "AES"), paramSpec); 
    byte[] decrypted = cipher.doFinal(encrypted); 
    System.out.println("decrypted: " + new String(decrypted)); 

그때 나는 오류 Invalid AES key length: 162 bytes

을 얻고, cipher.init(Cipher.DECRYPT_MODE, pubKey);에 암호 초기화를 변경하는 경우

답변

0

공개 키를 잘못 사용하고 있습니다. C# 프로그램이 어떻게 작동하는지 정말 이해하고 있습니까? 어떤 매개 변수를 사용하고 있습니까?

공개 키 비트를 AES 키로 사용하고 있습니다 (162 바이트를 얻는 방법을 실제로 이해하지 못하더라도).

이것은 "하이브리드 암호화"의 예입니다. 데이터 자체는 무작위 AES 키 (이것은 256 비트라고 주장합니다)와 AES 키 (이 경우 IV)는 RSA 공개에 의해 암호화됩니다 키. 자바에서는 examples how to do that이 많이 있습니다.

AES 키를 해독하는 경우에도 RSA/ECB/PKCS5Padding, RSA-AOEP, ... 등의 암호화에 사용 된 매개 변수를 알아야합니다 (XML 내부에 있어야 함).

매개 변수를 사용하는 경우 PKCS5Padding을 사용하고 있지만 .NET 코드를 확인하면 달라집니다.