패딩이 유효하지 않아 제거 할 수 없습니까?


126

내 프로그램과 관련하여이 예외가 의미하는 바를 온라인에서 찾았지만 솔루션이나 특정 프로그램에서 발생하는 이유를 찾을 수없는 것 같습니다. Rijndael 알고리즘을 사용하여 XmlDocument를 암호화하고 해독하기 위해 msdn을 제공 한 예제를 사용하고 있습니다. 암호화는 잘 작동하지만 암호를 해독하려고하면 다음 예외가 발생합니다.

패딩이 잘못되었으며 제거 할 수 없습니다.

누구든지이 문제를 해결하기 위해 내가 무엇을 할 수 있는지 말해 줄 수 있습니까? 아래 코드는 키 및 기타 데이터를 얻는 곳입니다. cryptoMode가 false이면 예외가 발생하는 decrypt 메서드를 호출합니다.

public void Cryptography(XmlDocument doc, bool cryptographyMode)
{
    RijndaelManaged key = null;
    try
    {
    // Create a new Rijndael key.
    key = new RijndaelManaged();
    const string passwordBytes = "Password1234"; //password here 

    byte[] saltBytes = Encoding.UTF8.GetBytes("SaltBytes");
    Rfc2898DeriveBytes p = new Rfc2898DeriveBytes(passwordBytes, saltBytes);
    // sizes are devided by 8 because [ 1 byte = 8 bits ] 
    key.IV = p.GetBytes(key.BlockSize/8);
    key.Key = p.GetBytes(key.KeySize/8);

    if (cryptographyMode)
    {
        Ecrypt(doc, "Content", key);
    }
    else
    {
        Decrypt(doc, key);
    }

    }
    catch (Exception ex)
    {
    MessageBox.Show(ex.Message);
    }
    finally
    {
    // Clear the key.
    if (key != null)
    {
        key.Clear();
    }
    }

}

private void Decrypt(XmlDocument doc, SymmetricAlgorithm alg)
{
    // Check the arguments.  
    if (doc == null)
    throw new ArgumentNullException("Doc");
    if (alg == null)
    throw new ArgumentNullException("alg");

    // Find the EncryptedData element in the XmlDocument.
    XmlElement encryptedElement = doc.GetElementsByTagName("EncryptedData")[0] as XmlElement;

    // If the EncryptedData element was not found, throw an exception.
    if (encryptedElement == null)
    {
    throw new XmlException("The EncryptedData element was not found.");
    }


    // Create an EncryptedData object and populate it.
    EncryptedData edElement = new EncryptedData();
    edElement.LoadXml(encryptedElement);

    // Create a new EncryptedXml object.
    EncryptedXml exml = new EncryptedXml();


    // Decrypt the element using the symmetric key.
    byte[] rgbOutput = exml.DecryptData(edElement, alg); <----  I GET THE EXCEPTION HERE
    // Replace the encryptedData element with the plaintext XML element.
    exml.ReplaceData(encryptedElement, rgbOutput);

}

12
암호화 및 복호화에서 패딩 모드를 명시 적으로 동일하게 설정하여 시도해 볼 수 있습니까? 예 : alg.Padding = PaddingMode.NONE;
NetSquirrel 2011

Encrypt () 메서드는 어떻게 생겼습니까?
csharptest.net 2011

1
일한 사람들에게 감사합니다.
Brown Love

2
@NetSquirrel : PaddingMode.NONE에 대한 알림을 보내 주셔서 감사합니다. 이 오류에서 벗어나게됩니다 (다른 오류로) ... Java와 C # 모두에서 AES를 수행하고 있으며 둘 다 PKCS # 7을 사용하지만 C #이 Java 패딩에 대해 불평하는 이유를 알 수 없습니다.
Hoàng Long

답변:


81

Rijndael / AES는 블록 사이퍼입니다. 128 비트 (16 문자) 블록의 데이터를 암호화합니다. 암호화 패딩 은 메시지의 마지막 블록이 항상 올바른 크기인지 확인하는 데 사용됩니다.

암호 해독 방법은 기본 패딩이 무엇이든 예상하고 찾지 못합니다. @NetSquirrel이 말했듯이 암호화와 복호화 모두에 대해 명시 적으로 패딩을 설정해야합니다. 다른 이유가없는 한 PKCS # 7 패딩을 사용하십시오.


7
패딩을 명시 적으로 설정하는 방법 ??
아마드 Hajjar

7
찾아 주셔서 감사합니다. rj.Padding = PaddingMode.none; :)
아마드 Hajjar

7
@AhmadHajjar 패딩은 보안에 영향을 미치지 않으므로 사용하지 마십시오.
deviantfan

1
안녕하세요, 패딩을 명시 적으로 설정했지만 작동하지 않습니다. 내가 뭘 잘못했는지 모르겠다. 도와주세요. alg.Padding = PaddingMode.PKCS7;
Johnny

21
나는 이것이 오래된 실이라는 것을 알고 있습니다. 그러나 방문하는 사람들의 경우 데이터를 암호화 할 때 최종 블록을 비워야합니다.
Markus

53

확인 키 당신이 사용하는 것이 확인 암호화암호 해독이 되어 같은 . 패딩 방법은 명시 적으로 설정되지 않은 경우에도 적절한 암호 해독 / 암호화를 허용해야합니다 (설정하지 않으면 동일 함). 어떤 이유로 당신은 암호화에 사용보다 암호 해독 키의 다른 세트를 사용하지만 경우에 당신은 이 오류가 발생합니다 :

패딩이 잘못되었으며 제거 할 수 없습니다.

일부 알고리즘을 사용하여 작동하지 않는 키를 동적으로 생성하는 경우. 암호화와 복호화 모두 동일해야합니다. 한 가지 일반적인 방법은 호출자가 암호화 메서드 클래스의 생성자에 키를 제공하도록하여 암호화 / 복호화 프로세스가 이러한 항목을 생성하는 데 도움이되지 않도록하는 것입니다. 그것은 당면한 작업 (데이터 암호화 및 해독)에 초점을 맞추고 호출자 가 ivkey을 제공해야합니다.


때때로 키가 app.config에 저장되고 암호화에 사용 된 키가 암호 해독에 사용 된 것과 동일한 지 항상 확인해야하기 때문에이 팁은 매우 유용했습니다.
Mário Meyrelles

@atconway 제 질문 좀 봐주 시겠어요? 비슷한 문제가 있지만 C ++ / CLI : stackoverflow.com/questions/57139447/…
Simple

1
나는 일상적인 사용에서 이것이 아마도 사람들 이이 오류를 보게 될 가장 가능성이 높은 이유라고 제안합니다. 특히 패딩 설정을 엉망으로 만들지 않는 경우.
Dan

28

검색하는 사람들의 이익을 위해 암호가 해독되는 입력을 확인하는 것이 좋습니다. 제 경우에는 암호 해독을 위해 전송되는 정보가 (잘못) 빈 문자열로 들어갔습니다. 패딩 오류가 발생했습니다.

이것은 rossum의 답변과 관련이있을 수 있지만 언급 할 가치가 있다고 생각했습니다.


동의합니다. 다른 검사를 수행하기 전에 입력이 해독되는지 확인하면서 동일한 일이 발생했습니다. 나는 ... 나는 encypted 것보다 1 바이트 이상을 얻고 있었다
안드레아 Antonangeli에게

빈 문자열이 저에게도 범인이었습니다.
소프 트

제 경우에는 암호가 설정되지 않았는데 (예, 알고 있습니다),이 대답은 저를 올바른 방향으로 인도했습니다.
Jim

2
내 문제는 해독 할 문자열이 해독을 시도하기 전에 소문자로 변환된다는 것입니다. 나는 패딩과 암호와 그 모든 것에 집착하고 있었지만 그것은 단지 잘못된 입력이라는 것이 밝혀졌습니다. 때로는 한 발 뒤로 물러 서면됩니다!
Tom Gerken

15

인코딩 및 디코딩에 동일한 키와 초기화 벡터를 사용하는 경우이 문제는 데이터 디코딩이 아니라 데이터 인코딩에서 발생합니다.

CryptoStream 개체에 대해 Write 메서드를 호출 한 후에는 항상 Close 메서드보다 먼저 FlushFinalBlock 메서드를 호출해야합니다.

CryptoStream.FlushFinalBlock 메서드에 대한 MSDN 설명서에
" Close 메서드를 호출하면 FlushFinalBlock이 호출됩니다 ... "
https://msdn.microsoft.com/en-US/library/system.security.cryptography.cryptostream.flushfinalblock(v=vs .110) .aspx
이것은 잘못되었습니다. Close 메서드를 호출하면 CryptoStream과 출력 Stream이 닫힙니다.
암호화 할 데이터를 작성한 후 Close 전에 FlushFinalBlock을 호출하지 않으면 데이터를 해독 할 때 CryptoStream 개체에서 Read 또는 CopyTo 메서드를 호출하면 CryptographicException 예외가 발생합니다 (메시지 : "패딩이 유효하지 않으며 제거 할 수 없습니다").

이것은 SymmetricAlgorithm (Aes, DES, RC2, Rijndael, TripleDES)에서 파생 된 모든 암호화 알고리즘에 해당 될 수 있지만 AesManaged 및 MemoryStream에 대해 출력 스트림으로 확인했습니다.

따라서 암호 해독시이 CryptographicException 예외가 발생하면 암호화 할 데이터를 작성한 후 출력 Stream Length 속성 값을 읽은 다음 FlushFinalBlock을 호출하고 해당 값을 다시 읽습니다. 변경된 경우 FlushFinalBlock 호출이 선택 사항이 아님을 알고 있습니다.

프로그래밍 방식으로 패딩을 수행하거나 다른 패딩 속성 값을 선택할 필요가 없습니다. 패딩은 FlushFinalBlock 메서드 작업입니다.

.........

Kevin에 대한 추가 설명 :

예, CryptoStream은 Close를 호출하기 전에 FlushFinalBlock을 호출하지만 너무 늦습니다. CryptoStream Close 메서드가 호출되면 출력 스트림도 닫힙니다.

출력 스트림이 MemoryStream 인 경우 닫힌 후 데이터를 읽을 수 없습니다. 따라서 MemoryStream에 기록 된 암호화 된 데이터를 사용하기 전에 CryptoStream에서 FlushFinalBlock을 호출해야합니다.

출력 스트림이 FileStream이면 쓰기가 버퍼링되기 때문에 상황이 더 나빠집니다. 결과적으로 FileStream에서 Flush를 호출하기 전에 출력 스트림을 닫으면 마지막으로 쓴 바이트가 파일에 기록되지 않을 수 있습니다. 따라서 CryptoStream에서 Close를 호출하기 전에 먼저 CryptoStream에서 FlushFinalBlock을 호출 한 다음 FileStream에서 Flush를 호출해야합니다.


1
왜 틀렸다고합니까? Stream.Close()통화 코드입니다 this.Dispose(true). 코드는 CryptoStream.Dispose(bool)다음과 같습니다if (disposing) { if (!this._finalBlockTransformed) { this.FlushFinalBlock(); } this._stream.Close(); }
케빈 Doyon

1
이것은 내 문제를 해결했습니다. 나는 cryptoStream을 올바르게 처리했지만 dispose 호출이 "너무 늦게"발생했습니다. 이로 인해 설명 된대로 "잘못된 패딩"오류가 발생했습니다. cryptoStream.FlushFinalBlock ()을 추가하여 잘못된 패딩 오류가 해결되었습니다. 감사!
Daniel Lambert

14

살벌한 싸움의 시간, 나는 마침내 문제를 해결했습니다.
(참고 : 대칭 알고리즘으로 표준 AES를 사용합니다.이 답변은 모든 사람에게 적합하지 않을 수 있습니다.)

  1. 알고리즘 클래스를 변경하십시오. RijndaelManaged클래스를 AESManaged하나로 바꿉니다 .
  2. KeySize알고리즘 클래스를 명시 적으로 설정하지 말고 기본값으로 두십시오.
    (이것은 매우 중요한 단계입니다. KeySize 속성에 버그가 있다고 생각합니다.)

놓친 인수를 확인하려는 목록은 다음과 같습니다.


  • (바이트 배열, 길이는 다른 키 크기에 대해 정확히 16, 24, 32 바이트 중 하나 여야합니다.)
  • IV
    (바이트 배열, 16 바이트)
  • CipherMode
    (CBC, CFB, CTS, ECB, OFB 중 하나)
  • PaddingMode
    (ANSIX923, ISO10126, None, PKCS7, Zeros 중 하나)

3
명시 적으로 설정하지 않으면 KeySize즉시 수정되었습니다. 오 .NET의 특질 :-(
John

이것은 .NET Framework 자체의 회귀 인 것 같습니다. RijndaelManaged와 함께 작동하는 데 사용되는 코드가 있지만 작동을 멈췄으며 단순히 AesManaged / AesCryptoServiceProvider로 변경하면 다시 작동합니다. KeySize를 명시 적으로 설정하는 코드도 없었습니다. 그래서 당신이 이것에 물렸다면 기분이 나아질 것입니다. 결함은 당신에게있는 것이 아니라 .NET Framework 자체에있을 수 있습니다.
Usas

6

내 문제는 암호화의 passPhrase가 decrypt의 passPhrase와 일치하지 않았기 때문에이 오류가 발생했습니다.


실제로 Encrypt 및 Decrypt에 PaddingMode.PKCS7을 사용하는 것은 사실이지만 동일한 오류 메시지가 나타납니다. 또한 키 값이 다른 Stage 및 Dev 환경이 있습니다. 적절한 환경 별 키를 사용했을 때이 예외가 해결되었습니다.
Major

위의 모든 답변이 훌륭하고 암호화 및 암호 해독에 대해 동일한 패딩을 사용해야하지만 (권장하지 않음) 실제로이 답변도 사실 일 수 있습니다. 적절한 환경 별 키를 사용할 때 "System.Security.Cryptography.CryptographicException : 패딩이 유효하지 않으며 제거 할 수 없습니다."라는 예외를 입력합니다. 해결되었습니다. 그렇습니다. 오해의 소지가 있습니다.
Major

"passPhrase"에 의해 암호화 / 암호 해독에 대한 정확한 값 (잘못된 키 사용에 대한 문제가 아님)에 대해 이야기하는 경우 예, 이것이 제 문제였습니다. 내 경우는 원래 암호화 된 값이 내 데이터베이스 테이블 필드가 허용하는 것보다 길어서 내가 알지 못하는 사이에 맞게 잘 렸습니다. 그런 다음 잘린 값을 해독 할 때이 예외가 발생했습니다.
David Gunderson

2

내 문제를 해결 한 해결책은 실수로 암호화 및 암호 해독 방법에 다른 키를 적용한 것입니다.


1

암호화되지 않은 파일 경로를 Decrypt 메서드에 전달하려고 시도하는 동안이 오류가 발생했습니다. 해결 방법은 암호 해독을 시도하기 전에 전달 된 파일이 먼저 암호화되었는지 확인하는 것입니다.

if (Sec.IsFileEncrypted(e.File.FullName))
{
    var stream = Sec.Decrypt(e.File.FullName);
} 
else
{
    // non-encrypted scenario  
}

1
이 솔루션의 유효성에 대해 Hit and Run Coward에 도전합니다.
usefulBee

이 예외는 두 번 복호화하거나 암호화되지 않은 것을 복호화 할 때 발생하기 때문입니다. 그래서 저는이 대답을 "데이터가 실제로 암호화 된 것이 확실합니까?"라고 읽었습니다.
Gerardo Grignoli

0

검색하는 사람들의 이익을위한 또 다른 시나리오입니다.

나를 위해이 오류는 암호화와 관련이없는 이전 오류를 마스킹 한 Dispose () 메서드 중에 발생했습니다.

다른 구성 요소가 수정되면이 예외가 사라졌습니다.


3
암호화와 관련이없는 이전 오류는 무엇입니까?
NStuke

0

암호화 된 콘텐츠가 수동으로 변경된 경우 암호 해독 기능이 어떻게 작동하는지 테스트하고 싶었 기 때문에 파일에서 암호화 된 문자열을 수동으로 편집 할 때 (메모장을 사용하여)이 패딩 오류가 발생했습니다.

나를위한 해결책은

        try
            decryption stuff....
        catch
             inform decryption will not be carried out.
        end try

내가 말했듯이 패딩 오류는 메모장을 사용하여 해독 된 텍스트 위에 수동으로 입력했기 때문입니다. 내 대답이 귀하의 솔루션을 안내 할 수 있습니다.


0

나는 같은 오류가 있었다. 제 경우에는 암호화 된 데이터를 SQL 데이터베이스에 저장했기 때문입니다. 데이터가 저장된 테이블은 이진 (1000) 데이터 유형을 갖습니다. 데이터베이스에서 데이터를 검색 할 때이 1000 바이트의 암호를 해독하는 반면 실제로는 400 바이트입니다. 따라서 결과에서 후행 0 (600)을 제거하면 문제가 해결되었습니다.


0

이 오류가 있었고 블록 크기를 명시 적으로 설정했습니다. aesManaged.BlockSize = 128;

그것을 제거하면 작동했습니다.


0

Go 프로그램을 C #으로 이식하는 데 동일한 문제가 발생했습니다. 이것은 많은 데이터가 이미 Go 프로그램으로 암호화되었음을 의미합니다. 이 데이터는 이제 C #으로 해독해야합니다.

최종 해결책은 PaddingMode.None또는 오히려 PaddingMode.Zeros.

Go의 암호화 방법 :

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/sha1"
    "encoding/base64"
    "io/ioutil"
    "log"

    "golang.org/x/crypto/pbkdf2"
)

func decryptFile(filename string, saltBytes []byte, masterPassword []byte) (artifact string) {

    const (
        keyLength         int = 256
        rfc2898Iterations int = 6
    )

    var (
        encryptedBytesBase64 []byte // The encrypted bytes as base64 chars
        encryptedBytes       []byte // The encrypted bytes
    )

    // Load an encrypted file:
    if bytes, bytesErr := ioutil.ReadFile(filename); bytesErr != nil {
        log.Printf("[%s] There was an error while reading the encrypted file: %s\n", filename, bytesErr.Error())
        return
    } else {
        encryptedBytesBase64 = bytes
    }

    // Decode base64:
    decodedBytes := make([]byte, len(encryptedBytesBase64))
    if countDecoded, decodedErr := base64.StdEncoding.Decode(decodedBytes, encryptedBytesBase64); decodedErr != nil {
        log.Printf("[%s] An error occur while decoding base64 data: %s\n", filename, decodedErr.Error())
        return
    } else {
        encryptedBytes = decodedBytes[:countDecoded]
    }

    // Derive key and vector out of the master password and the salt cf. RFC 2898:
    keyVectorData := pbkdf2.Key(masterPassword, saltBytes, rfc2898Iterations, (keyLength/8)+aes.BlockSize, sha1.New)
    keyBytes := keyVectorData[:keyLength/8]
    vectorBytes := keyVectorData[keyLength/8:]

    // Create an AES cipher:
    if aesBlockDecrypter, aesErr := aes.NewCipher(keyBytes); aesErr != nil {
        log.Printf("[%s] Was not possible to create new AES cipher: %s\n", filename, aesErr.Error())
        return
    } else {

        // CBC mode always works in whole blocks.
        if len(encryptedBytes)%aes.BlockSize != 0 {
            log.Printf("[%s] The encrypted data's length is not a multiple of the block size.\n", filename)
            return
        }

        // Reserve memory for decrypted data. By definition (cf. AES-CBC), it must be the same lenght as the encrypted data:
        decryptedData := make([]byte, len(encryptedBytes))

        // Create the decrypter:
        aesDecrypter := cipher.NewCBCDecrypter(aesBlockDecrypter, vectorBytes)

        // Decrypt the data:
        aesDecrypter.CryptBlocks(decryptedData, encryptedBytes)

        // Cast the decrypted data to string:
        artifact = string(decryptedData)
    }

    return
}

... 그리고 ...

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/sha1"
    "encoding/base64"
    "github.com/twinj/uuid"
    "golang.org/x/crypto/pbkdf2"
    "io/ioutil"
    "log"
    "math"
    "os"
)

func encryptFile(filename, artifact string, masterPassword []byte) (status bool) {

    const (
        keyLength         int = 256
        rfc2898Iterations int = 6
    )

    status = false
    secretBytesDecrypted := []byte(artifact)

    // Create new salt:
    saltBytes := uuid.NewV4().Bytes()

    // Derive key and vector out of the master password and the salt cf. RFC 2898:
    keyVectorData := pbkdf2.Key(masterPassword, saltBytes, rfc2898Iterations, (keyLength/8)+aes.BlockSize, sha1.New)
    keyBytes := keyVectorData[:keyLength/8]
    vectorBytes := keyVectorData[keyLength/8:]

    // Create an AES cipher:
    if aesBlockEncrypter, aesErr := aes.NewCipher(keyBytes); aesErr != nil {
        log.Printf("[%s] Was not possible to create new AES cipher: %s\n", filename, aesErr.Error())
        return
    } else {

        // CBC mode always works in whole blocks.
        if len(secretBytesDecrypted)%aes.BlockSize != 0 {
            numberNecessaryBlocks := int(math.Ceil(float64(len(secretBytesDecrypted)) / float64(aes.BlockSize)))
            enhanced := make([]byte, numberNecessaryBlocks*aes.BlockSize)
            copy(enhanced, secretBytesDecrypted)
            secretBytesDecrypted = enhanced
        }

        // Reserve memory for encrypted data. By definition (cf. AES-CBC), it must be the same lenght as the plaintext data:
        encryptedData := make([]byte, len(secretBytesDecrypted))

        // Create the encrypter:
        aesEncrypter := cipher.NewCBCEncrypter(aesBlockEncrypter, vectorBytes)

        // Encrypt the data:
        aesEncrypter.CryptBlocks(encryptedData, secretBytesDecrypted)

        // Encode base64:
        encodedBytes := make([]byte, base64.StdEncoding.EncodedLen(len(encryptedData)))
        base64.StdEncoding.Encode(encodedBytes, encryptedData)

        // Allocate memory for the final file's content:
        fileContent := make([]byte, len(saltBytes))
        copy(fileContent, saltBytes)
        fileContent = append(fileContent, 10)
        fileContent = append(fileContent, encodedBytes...)

        // Write the data into a new file. This ensures, that at least the old version is healthy in case that the
        // computer hangs while writing out the file. After a successfully write operation, the old file could be
        // deleted and the new one could be renamed.
        if writeErr := ioutil.WriteFile(filename+"-update.txt", fileContent, 0644); writeErr != nil {
            log.Printf("[%s] Was not able to write out the updated file: %s\n", filename, writeErr.Error())
            return
        } else {
            if renameErr := os.Rename(filename+"-update.txt", filename); renameErr != nil {
                log.Printf("[%s] Was not able to rename the updated file: %s\n", fileContent, renameErr.Error())
            } else {
                status = true
                return
            }
        }

        return
    }
}

이제 C #에서 암호 해독 :

public static string FromFile(string filename, byte[] saltBytes, string masterPassword)
{
    var iterations = 6;
    var keyLength = 256;
    var blockSize = 128;
    var result = string.Empty;
    var encryptedBytesBase64 = File.ReadAllBytes(filename);

    // bytes -> string:
    var encryptedBytesBase64String = System.Text.Encoding.UTF8.GetString(encryptedBytesBase64);

    // Decode base64:
    var encryptedBytes = Convert.FromBase64String(encryptedBytesBase64String);
    var keyVectorObj = new Rfc2898DeriveBytes(masterPassword, saltBytes.Length, iterations);
    keyVectorObj.Salt = saltBytes;
    Span<byte> keyVectorData = keyVectorObj.GetBytes(keyLength / 8 + blockSize / 8);
    var key = keyVectorData.Slice(0, keyLength / 8);
    var iv = keyVectorData.Slice(keyLength / 8);

    var aes = Aes.Create();
    aes.Padding = PaddingMode.Zeros;
    // or ... aes.Padding = PaddingMode.None;
    var decryptor = aes.CreateDecryptor(key.ToArray(), iv.ToArray());
    var decryptedString = string.Empty;

    using (var memoryStream = new MemoryStream(encryptedBytes))
    {
        using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
        {
            using (var reader = new StreamReader(cryptoStream))
            {
                decryptedString = reader.ReadToEnd();
            }
        }
    }

    return result;
}

패딩 문제를 어떻게 설명 할 수 있습니까? 암호화 직전에 Go 프로그램은 패딩을 확인합니다.

// CBC mode always works in whole blocks.
if len(secretBytesDecrypted)%aes.BlockSize != 0 {
    numberNecessaryBlocks := int(math.Ceil(float64(len(secretBytesDecrypted)) / float64(aes.BlockSize)))
    enhanced := make([]byte, numberNecessaryBlocks*aes.BlockSize)
    copy(enhanced, secretBytesDecrypted)
    secretBytesDecrypted = enhanced
}

중요한 부분은 다음과 같습니다.

enhanced := make([]byte, numberNecessaryBlocks*aes.BlockSize)
copy(enhanced, secretBytesDecrypted)

길이가 블록 크기의 배수가되도록 적절한 길이로 새 배열이 작성됩니다. 이 새 배열은 0으로 채워집니다. 그런 다음 복사 방법은 기존 데이터를 여기에 복사합니다. 새 어레이가 기존 데이터보다 큰지 확인합니다. 따라서 배열 끝에 0이 있습니다.

따라서 C # 코드는 PaddingMode.Zeros. 대안 PaddingMode.None은 패딩을 무시하고 작동합니다. 이 답변이 Go에서 C # 등으로 코드를 이식해야하는 모든 사람에게 도움이되기를 바랍니다.


0

클라이언트에서 동일한 오류를보고했습니다. 나는 개인적으로 그것을 재현 할 수 없습니다. EncryptDecrypt 메서드 의 코드를 보면 둘 다 PaddingPaddingMode.PKCS7로 설정되어 있습니다 . Decrypt 는 다음과 같이 보이며 ' FlushFinalBlock ' 과 관련하여 문제를 볼 수 없습니다 . 누군가 그것에 대해 약간의 빛을 비추어 줄 수 있습니까?

public string Decrypt(string cipherText)
{
  if (string.IsNullOrEmpty(cipherText))
    return "";
  string result;
  Encoding byteEncoder = Encoding.Default;

  byte[] rijnKey = byteEncoder.GetBytes(Password);
  byte[] rijnIv = byteEncoder.GetBytes(InitialVector);
  RijndaelManaged rijn = new RijndaelManaged { Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };

  using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
  {
    using (ICryptoTransform decryptor = rijn.CreateDecryptor(rijnKey, rijnIv))
    {
      using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
      {
                    using (StreamReader swDecrypt = new StreamReader(csDecrypt))
                    {
                        result = swDecrypt.ReadToEnd();
                    }
                }
    }
  }
  rijn.Clear();      
  return result.Replace("\0", "");
}

0

나는 같은 오류가 있었다. 제 경우에는 주어진 암호가 16보다 크면 암호화되었음을 의미하지만 암호 해독 중에이 오류가 발생합니다. 암호화 :

string keyString = "CDFUYP@ssw0rd123";
            var key = Encoding.UTF8.GetBytes(keyString);            
            using (var aesAlg = Aes.Create())
            {
                using (var encryptor = aesAlg.CreateEncryptor(key, aesAlg.IV))
                {
                    using (var msEncrypt = new MemoryStream())
                    {
                        using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                        using (var swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(text);
                        }                          
                        var iv = aesAlg.IV;

                        var decryptedContent = msEncrypt.ToArray();

                        var result = new byte[iv.Length + decryptedContent.Length];

                        Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
                        Buffer.BlockCopy(decryptedContent, 0, result, iv.Length, decryptedContent.Length);

                        var encryptedString = Convert.ToBase64String(result);
                        var decryptedString = Decrypt(encryptedString);
                        if (decryptedString == null)
                        {
                            return null;
                        }
                        return encryptedString;

                    }
                }

복호화 :

 string keyString = "CDFUYP@ssw0rd123";
            var fullCipher = Convert.FromBase64String(cipherText);
            var iv = new byte[16];
            var cipher = new byte[16];
            Buffer.BlockCopy(fullCipher, 0, iv, 0, iv.Length);
            Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, iv.Length);
            var key = Encoding.UTF8.GetBytes(keyString);

            using (var aesAlg = Aes.Create())
            {
                using (var decryptor = aesAlg.CreateDecryptor(key, iv))
                {
                    string result;
                    using (var msDecrypt = new MemoryStream(cipher))
                    {
                        using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                        {
                            using (var srDecrypt = new StreamReader(csDecrypt))
                            {
                                result = srDecrypt.ReadToEnd();
                            }
                        }
                    }

                    return result;
                }
            }

@sundarraj 님,이게 질문인가요?
Tiago Martins Peres 李大仁
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.