• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

famoser / elliptic / 16238145859

12 Jul 2025 12:46PM UTC coverage: 84.857% (-6.3%) from 91.134%
16238145859

Pull #12

github

web-flow
Merge fe4ab825d into 5ce1049c0
Pull Request #12: WIP: Add montgomery

270 of 376 new or added lines in 17 files covered. (71.81%)

2 existing lines in 1 file now uncovered.

947 of 1116 relevant lines covered (84.86%)

23.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Serializer/SECSerializer.php
1
<?php
2

3
namespace Famoser\Elliptic\Serializer;
4

5
use Famoser\Elliptic\Primitives\Curve;
6
use Famoser\Elliptic\Primitives\Point;
7
use Famoser\Elliptic\Serializer\PointDecoder\PointDecoderException;
8
use Famoser\Elliptic\Serializer\SEC\SECEncoding;
9
use Famoser\Elliptic\Serializer\SEC\SECPointDecoderInterface;
10

11
/**
12
 * implements serialization as described in https://www.secg.org/SEC1-Ver-1.0.pdf
13
 */
14
class SECSerializer
15
{
16
    private readonly int $pointOctetLength;
17

NEW
18
    public function __construct(private readonly Curve $curve, private readonly SECPointDecoderInterface $pointDecoder, private readonly SECEncoding $preferredEncoding = SECEncoding::COMPRESSED)
×
19
    {
20
        $this->pointOctetLength = (int) ceil((float) strlen(gmp_strval($this->curve->getP(), 2)) / 8);
×
21
    }
22

23
    /**
24
     * implements https://wdecoderww.secg.org/SEC1-Ver-1.0.pdf 2.3.4
25
     *
26
     * @throws PointDecoderException|SerializerException
27
     */
28
    public function deserialize(string $hex): Point
×
29
    {
30
        if ($hex === '00') {
×
31
            return Point::createInfinity();
×
32
        }
33

34
        $compressedFormatOctetLength = 1 + $this->pointOctetLength;
×
35
        if (strlen($hex) === 2 * $compressedFormatOctetLength && (str_starts_with($hex, '02') || str_starts_with($hex, '03'))) {
×
36
            $x = gmp_init(substr($hex, 2), 16);
×
37
            $isEvenY = str_starts_with($hex, '02');
×
38

39
            return $this->pointDecoder->fromXCoordinate($x, $isEvenY);
×
40
        }
41

42
        $uncompressedFormatOctetLength = 1 + 2 * $this->pointOctetLength;
×
43
        if (strlen($hex) === 2 * $uncompressedFormatOctetLength && str_starts_with($hex, '04')) {
×
44
            $pointHexLength = 2 * $this->pointOctetLength;
×
45
            $x = gmp_init(substr($hex, 2, $pointHexLength), 16);
×
46
            $y = gmp_init(substr($hex, 2 + $pointHexLength), 16);
×
47

48
            return $this->pointDecoder->fromCoordinates($x, $y);
×
49
        }
50

NEW
51
        throw new SerializerException('Unknown deserialization format.');
×
52
    }
53

54
    /**
55
     * implements https://www.secg.org/SEC1-Ver-1.0.pdf 2.3.3
56
     */
57
    public function serialize(Point $point): string
×
58
    {
59
        if ($point->isInfinity()) {
×
60
            return '00';
×
61
        }
62

63
        return match ($this->preferredEncoding) {
×
NEW
64
            SECEncoding::COMPRESSED => $this->serializeCompressed($point),
×
NEW
65
            SECEncoding::UNCOMPRESSED => $this->serializeUncompressed($point)
×
66
        };
×
67
    }
68

69
    private function serializeCompressed(Point $point): string
×
70
    {
71
        $x = str_pad(gmp_strval($point->x, 16), $this->pointOctetLength * 2, '0', STR_PAD_LEFT);
×
72

73
        $isEven = gmp_cmp(gmp_mod($point->y, 2), 0);
×
74
        $prefix = $isEven ? '02' : '03';
×
75

76
        return $prefix . $x;
×
77
    }
78

79
    private function serializeUncompressed(Point $point): string
×
80
    {
81
        $x = str_pad(gmp_strval($point->x, 16), $this->pointOctetLength * 2, '0', STR_PAD_LEFT);
×
82
        $y = str_pad(gmp_strval($point->y, 16), $this->pointOctetLength * 2, '0', STR_PAD_LEFT);
×
83

84
        return '04' . $x . $y;
×
85
    }
86
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc