GithubHelp home page GithubHelp logo

Comments (13)

singpolyma avatar singpolyma commented on August 14, 2024

The MDC packet contains only a sha1 hash in its body. So the whole packet is always "\xD3\x14" . $sha1_in_binary

In our code I use

$prefix = Random::string($key_block_bytes);
$prefix .= substr($prefix, -2);
$to_encrypt = $prefix . $message->to_bytes();
hash('sha1', $to_encrypt . "\xD3\x14", true) // to produce the sha1

For full implementation, see https://github.com/singpolyma/openpgp-php/blob/master/lib/openpgp_crypt_symmetric.php

from openpgp-php.

DanielRuf avatar DanielRuf commented on August 14, 2024

But what to do then? I already saw this code and se it in a current test. Append it to the plaintext and encrypt the whole or encrypt plaintext as always and then append the MDC packet?

from openpgp-php.

singpolyma avatar singpolyma commented on August 14, 2024

encrypt $to_encrypt . $mdc_packet->to_bytes()

from openpgp-php.

DanielRuf avatar DanielRuf commented on August 14, 2024

It is a bit more complicated. I think I have to rewrite many parts and do it in some other way as we use directly the plaintext (not as bytes).

It seems to_bytes appends some more data depending on the hash algorithm and other parameters so this is not directly portable for us.

https://github.com/singpolyma/openpgp-php/blob/d37e91efdae960582b7932cf2be7d59c1894c3b1/lib/openpgp.php

And this is where it is a bit unclear to me how the resulting structure and bytes look like.

The body is this (if I am right)?
[\xD3] [\x14] [bytes of the sha1 hash of the plaintext message]

And what does the header look like (what is done in the to_bytes function), or is this not needed?

from openpgp-php.

singpolyma avatar singpolyma commented on August 14, 2024

[\xD3] [\x14] is the header for the MDC packet (you can see that done in the ModificationDetectionCode class body method)

from openpgp-php.

DanielRuf avatar DanielRuf commented on August 14, 2024

But what is the result of $mdc_packet->to_bytes()? I am a bit confused now because [\xD3] [\x14] is already the header of the MDC packet. But wich to_bytes implementation is used?

Isn't this unnecessary?

return array('header' => $tag.$size, 'body' => $body);
  }
  function to_bytes() {
    $data = $this->header_and_body();
    return $data['header'].$data['body'];
  }

It gives just the header and body but the value of $mdc_packet is already header + body?

from openpgp-php.

singpolyma avatar singpolyma commented on August 14, 2024

function to_bytes() {

so to_bytes is just $header . $body for mdc those are: array('header' => "\xD3\x14", 'body' => $body); where $body is the binary sha1 result

from openpgp-php.

DanielRuf avatar DanielRuf commented on August 14, 2024

Right. So the to_bytes function call isn't really necessary here like I mentioned? I see no change before and after calling to_bytes here.

from openpgp-php.

singpolyma avatar singpolyma commented on August 14, 2024

No change where? I don't know how your code works. In my code, to_bytes just returns the full bytes for a packet (header and body both).

from openpgp-php.

DanielRuf avatar DanielRuf commented on August 14, 2024

So it is just

[ header    ] [ body                                          ]
[\xD3] [\x14] [binary sha1 hash(prefix + plaintext message + \xD3 \x14)] 

?

I think I understand it now.
But I don't see a viable reason why we have to recalculate the width of the body, which is a SHA-1 hash (always 20 chars / bytes long).

So far I have this:

    private function gpg_data($key, $text)
    {   
        $key_block_bytes=4096/8;
        $prefix = GPG_Utility::s_random($key_block_bytes,0);
        $prefix .= substr($prefix, -2);
        $text_bytes = $text; // what to do here?
        $mdc="\xD3\x14".sha1($prefix.$text_bytes." \xD3 \x14", true);
        $enc = $this->gpg_encrypt($key, $this->gpg_literal($text).$mdc);
        return $this->gpg_header(0xa4, strlen($enc)) . $enc;
    }

The result of --list-packets is

:encrypted data packet:
        length: 67
:literal data packet:
        mode t (74), created 0, name="file",
        raw data: 15 bytes
:mdc packet: length=20
gpg: WARNUNG: Botschaft wurde nicht integritätsgeschützt (integrity protected)

Compared to a message generated with GPA:

:encrypted data packet:
        length: 74
        mdc_method: 2
:compressed packet: algo=2
:literal data packet:
        mode b (62), created 1449226013, name="",
        raw data: 15 bytes

from openpgp-php.

singpolyma avatar singpolyma commented on August 14, 2024

$mdc="\xD3\x14".sha1($prefix.$text_bytes." \xD3 \x14", true);

this line has an extra space in the trailer literal. Also make sure you are using an integrityprotectedatapacket to wrap the encrypted result and not the normal encrypteddatapacket.

from openpgp-php.

DanielRuf avatar DanielRuf commented on August 14, 2024

Still unsure what we have to do in our php-gpg library to get this working. I'm confused and do not see the revelant parts where I have to change something and the RFC gives me not any helpful details.

private function gpg_data($key, $text)
    {   
        $key_block_bytes=4096/8;
        $prefix = GPG_Utility::s_random($key_block_bytes,0);
        $prefix .= substr($prefix, -2);
        $text_bytes = $text; // what to do here?
        $mdc="\xD3\x14".sha1($prefix.$text_bytes."\xD3\x14", true);
        var_dump($mdc);
        $enc = $this->gpg_encrypt($key, $this->gpg_literal($text).$mdc);
        return $this->gpg_header(0xa4, strlen($enc)) . $enc;
    }
private function gpg_literal($text)
    {
        if (strpos($text, "\r\n") === false)
            $text = str_replace("\n", "\r\n", $text);

        return
        $this->gpg_header(0xac, strlen($text) + 10) . "t" .
            chr(4) . "file\0\0\0\0" . $text;
    }
private function gpg_encrypt($key, $text) {

        $i = 0;
        $len = strlen($text);
        $iblock = array_fill(0, $this->width, 0);
        $rblock = array_fill(0, $this->width, 0);
        $ct = array_fill(0, $this->width + 2, 0);

        $cipher = "";

        if($len % $this->width) {
            for($i = ($len % $this->width); $i < $this->width; $i++) $text .= "\0";
        }

        $ekey = new Expanded_Key($key);

        for($i = 0; $i < $this->width; $i++) {
            $iblock[$i] = 0;
            $rblock[$i] = GPG_Utility::c_random();
        }


        $iblock = GPG_AES::encrypt($iblock, $ekey);
        for($i = 0; $i < $this->width; $i++) {
            $ct[$i] = ($iblock[$i] ^= $rblock[$i]);
        }

        $iblock = GPG_AES::encrypt($iblock, $ekey);
        $ct[$this->width]   = ($iblock[0] ^ $rblock[$this->width - 2]);
        $ct[$this->width + 1] = ($iblock[1] ^ $rblock[$this->width - 1]);

        for($i = 0; $i < $this->width + 2; $i++) $cipher .= chr($ct[$i]);

        $iblock = array_slice($ct, 2, $this->width + 2);

        for($n = 0; $n < strlen($text); $n += $this->width) {
            $iblock = GPG_AES::encrypt($iblock, $ekey);
            for($i = 0; $i < $this->width; $i++) {
                $iblock[$i] ^= ord($text[$n + $i]);
                $cipher .= chr($iblock[$i]);
            }
        }

        return substr($cipher, 0, $len + $this->width + 2);
    }
private function gpg_header($tag, $len)
    {
        $h = "";
        if ($len < 0x100) {
          $h .= chr($tag);
          $h .= chr($len);
        } else if ($len < 0x10000) {
          $tag+=1;
          $h .= chr($tag);
          $h .= $this->writeNumber($len, 2);
        } else {
          $tag+=2;
          $h .= chr($tag);
          $h .= $this->writeNumber($len, 4);
        }
        return $h;
    }

from openpgp-php.

singpolyma avatar singpolyma commented on August 14, 2024

jasonhinkle/php-gpg#20

from openpgp-php.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.