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

famoser / elliptic / 14023751500

23 Mar 2025 10:46PM UTC coverage: 74.33%. First build
14023751500

Pull #7

github

web-flow
Merge dd216c2e3 into 82f3ef4f9
Pull Request #7: Add safe math for sepk

272 of 336 new or added lines in 16 files covered. (80.95%)

388 of 522 relevant lines covered (74.33%)

12.65 hits per line

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

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

3
namespace Famoser\Elliptic\Serializer;
4

5
use Famoser\Elliptic\Primitives\Curve;
6
use Famoser\Elliptic\Primitives\Point;
7

8
/**
9
 * TODO implement https://www.secg.org/SEC1-Ver-1.0.pdf
10
 */
11
class PointSerializer
12
{
13
    private readonly int $pointOctetLength;
14
    private readonly PointDecoder $pointDecoder;
15

NEW
16
    public function __construct(private readonly Curve $curve, private readonly PointEncoding $preferredEncoding = PointEncoding::ENCODING_COMPRESSED)
×
17
    {
18
        $this->pointOctetLength = (int) ceil((float) strlen(gmp_strval($this->curve->getP(), 2)) / 8);
×
19
        $this->pointDecoder = new PointDecoder($this->curve);
×
20
    }
21

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

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

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

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

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

50
        throw new PointSerializerException('Unknown deserialization format.');
×
51
    }
52

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

NEW
62
        return match ($this->preferredEncoding) {
×
NEW
63
            PointEncoding::ENCODING_COMPRESSED => $this->serializeCompressed($point),
×
NEW
64
            PointEncoding::ENCODING_UNCOMPRESSED => $this->serializeUncompressed($point)
×
NEW
65
        };
×
66
    }
67

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

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

NEW
75
        return $prefix . $x;
×
76
    }
77

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

NEW
83
        return '04' . $x . $y;
×
84
    }
85
}
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