src/FreeDSx/Asn1/Encoder/CerDerTrait.php
protected function encodeSetOf(SetOfType $setOf)
    {
        if (\count($setOf->getChildren()) === 0) {
            return '';
        }
        $children = [];

        # Encode each child and record the length, we need it later
        foreach ($setOf as $type) {
            $child = ['original' => $this->encode($type)];
            $child['length'] = \strlen($child['original']);
            $children[] = $child;
        }

        # Sort the encoded types by length first to determine the padding needed.
        \usort($children, function ($a, $b) {
            /* @var AbstractType $a
             * @var AbstractType $b */
            return $a['length'] < $b['length'] ? -1 : 1;
        });

        # Get the last child (ie. the longest), and put the array back to normal.
        $child = \end($children);
        $padding = $child ['length'];
        \reset($children);

        # Sort by padding the items and comparing them.
        \usort($children, function($a, $b) use ($padding) {
            return \strcmp(
                \str_pad($a['original'], $padding, "\x00"),
                \str_pad($b['original'], $padding, "\x00")
            );
        });

        # Reconstruct the byte string from the order obtained.
        $bytes = '';
        foreach ($children as $child) {
            $bytes .= $child['original'];
        }

        return $bytes;
    }
protected function encodeSetOf(SetOfType $setOf)
    {
        if (\count($setOf->getChildren()) === 0) {
            return '';
        }
        $children = [];

        # Encode each child and record the length, we need it later
        foreach ($setOf as $type) {
            $child = ['original' => $this->encode($type)];
            $child['length'] = \strlen($child['original']);
            $children[] = $child;
        }

        # Sort the encoded types by length first to determine the padding needed.
        \usort($children, function ($a, $b) {
            /* @var AbstractType $a
             * @var AbstractType $b */
            return $a['length'] < $b['length'] ? -1 : 1;
        });

        # Get the last child (ie. the longest), and put the array back to normal.
        $child = \end($children);
        $padding = $child ['length'];
        \reset($children);

        # Sort by padding the items and comparing them.
        \usort($children, function($a, $b) use ($padding) {
            return \strcmp(
                \str_pad($a['original'], $padding, "\x00"),
                \str_pad($b['original'], $padding, "\x00")
            );
        });

        # Reconstruct the byte string from the order obtained.
        $bytes = '';
        foreach ($children as $child) {
            $bytes .= $child['original'];
        }

        return $bytes;
    }
protected function encodeSetOf ( SetOfType $ setOf ) { if ( \ count ( $ setOf -> getChildren ( ) ) === 0 ) { return '' ; } $ children = [ ] ; # Encode each child and record the length, we need it later foreach ( $ setOf as $ type ) { $ child = [ 'original' => $ this -> encode ( $ type ) ] ; $ child [ 'length' ] = \ strlen ( $ child [ 'original' ] ) ; $ children [ ] = $ child ; } # Sort the encoded types by length first to determine the padding needed. \ usort ( $ children , function ( $ a , $ b ) { /* @var AbstractType $a
             * @var AbstractType $b */ return $ a [ 'length' ] < $ b [ 'length' ] ? - 1 : 1 ; } ) ; # Get the last child (ie. the longest), and put the array back to normal. $ child = \ end ( $ children ) ; $ padding = $ child [ 'length' ] ; \ reset ( $ children ) ; # Sort by padding the items and comparing them. \ usort ( $ children , function ( $ a , $ b ) use ( $ padding ) { return \ strcmp ( \ str_pad ( $ a [ 'original' ] , $ padding , "\x00" ) , \ str_pad ( $ b [ 'original' ] , $ padding , "\x00" ) ) ; } ) ; # Reconstruct the byte string from the order obtained. $ bytes = '' ; foreach ( $ children as $ child ) { $ bytes .= $ child [ 'original' ] ; } return $ bytes ; }
X.690 Section 11.6

The encodings of the component values of a set-of value shall appear in ascending order, the encodings being
compared as octet strings with the shorter components being padded at their trailing end with 0-octets.

NOTE – The padding octets are for comparison purposes only and do not appear in the encodings.

---------

It's very hard to find examples, but it's not clear to me from the wording if I have this correct. The example I
did find in "ASN.1 Complete" (John Larmouth) contains seemingly several encoding errors:

- Length is not encoded correctly for the SET OF element.
- The integer 10 is encoded incorrectly.
- The sort is in descending order of the encoded value (in opposition to X.690 11.6), though in ascending
order of the literal integer values.

So I'm hesitant to trust that. Perhaps there's an example elsewhere to be used? Tests around this are hard to
come by in ASN.1 libraries for some reason.

@todo Is this assumed ordering correct? Confirmation needed. This could probably be simplified too.
@param SetOfType $setOf
@return string
X . 690 Section 11 . 6