diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2a34f186..19dd4559 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,4 +80,4 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - php-version: ['8.1'] + php-version: ['8.2'] diff --git a/phpseclib/Crypt/Common/AsymmetricKey.php b/phpseclib/Crypt/Common/AsymmetricKey.php index 51ebd5c6..f7ecfd34 100644 --- a/phpseclib/Crypt/Common/AsymmetricKey.php +++ b/phpseclib/Crypt/Common/AsymmetricKey.php @@ -152,6 +152,7 @@ abstract class AsymmetricKey } $components['format'] = $format; + $components['secret'] = $components['secret'] ?? ''; $comment = $components['comment'] ?? null; $new = static::onLoad($components); $new->format = $format; @@ -225,6 +226,7 @@ abstract class AsymmetricKey } $components['format'] = $format; + $components['secret'] = $components['secret'] ?? ''; $new = static::onLoad($components); $new->format = $format; diff --git a/phpseclib/Crypt/Common/SymmetricKey.php b/phpseclib/Crypt/Common/SymmetricKey.php index 63e1381a..a7724762 100644 --- a/phpseclib/Crypt/Common/SymmetricKey.php +++ b/phpseclib/Crypt/Common/SymmetricKey.php @@ -211,6 +211,11 @@ abstract class SymmetricKey */ protected $key = false; + /** + * @var null|string + */ + private $hKey = null; + /** * The Initialization Vector * @@ -264,9 +269,83 @@ abstract class SymmetricKey protected $debuffer; /** - * @var array + * mcrypt resource for encryption + * + * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. + * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. + * + * @see self::encrypt() + * @var resource */ - protected $buffer; + private $enmcrypt; + + /** + * mcrypt resource for decryption + * + * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. + * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. + * + * @see self::decrypt() + * @var resource + */ + private $demcrypt; + + /** + * Does the enmcrypt resource need to be (re)initialized? + * + * @see \phpseclib3\Crypt\Twofish::setKey() + * @see \phpseclib3\Crypt\Twofish::setIV() + * @var bool + */ + private $enchanged = true; + + /** + * Does the demcrypt resource need to be (re)initialized? + * + * @see \phpseclib3\Crypt\Twofish::setKey() + * @see \phpseclib3\Crypt\Twofish::setIV() + * @var bool + */ + private $dechanged = true; + + /** + * mcrypt resource for CFB mode + * + * mcrypt's CFB mode, in (and only in) buffered context, + * is broken, so phpseclib implements the CFB mode by it self, + * even when the mcrypt php extension is available. + * + * In order to do the CFB-mode work (fast) phpseclib + * use a separate ECB-mode mcrypt resource. + * + * @link http://phpseclib.sourceforge.net/cfb-demo.phps + * @see self::encrypt() + * @see self::decrypt() + * @see self::setupMcrypt() + * @var resource + */ + private $ecb; + + /** + * Optimizing value while CFB-encrypting + * + * Only relevant if $continuousBuffer enabled + * and $engine == self::ENGINE_MCRYPT + * + * It's faster to re-init $enmcrypt if + * $buffer bytes > $cfb_init_len than + * using the $ecb resource furthermore. + * + * This value depends of the chosen cipher + * and the time it would be needed for it's + * initialization [by mcrypt_generic_init()] + * which, typically, depends on the complexity + * on its internaly Key-expanding algorithm. + * + * @see self::encrypt() + * @var int + */ + protected $cfb_init_len = 600; /** * Does internal cipher state need to be (re)initialized? @@ -1308,7 +1387,7 @@ abstract class SymmetricKey $plaintext = ''; if ($this->continuousBuffer) { $iv = &$this->decryptIV; - $pos = &$this->buffer['pos']; + $pos = &$this->debuffer['pos']; } else { $iv = $this->decryptIV; $pos = 0; @@ -2844,7 +2923,7 @@ PHP private function setupGCM(): void { // don't keep on re-calculating $this->h - if (!$this->h || $this->h->key != $this->key) { + if (!$this->h || $this->hKey != $this->key) { $cipher = new static('ecb'); $cipher->setKey($this->key); $cipher->disablePadding(); @@ -2852,7 +2931,7 @@ PHP $this->h = self::$gcmField->newInteger( Strings::switchEndianness($cipher->encrypt("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) ); - $this->h->key = $this->key; + $this->hKey = $this->key; } if (strlen($this->nonce) == 12) { diff --git a/phpseclib/Crypt/DES.php b/phpseclib/Crypt/DES.php index ee2f04ee..a1e55e4e 100644 --- a/phpseclib/Crypt/DES.php +++ b/phpseclib/Crypt/DES.php @@ -127,7 +127,7 @@ class DES extends BlockCipher /** * @var array */ - private $kl; + private $kl = []; /** * Shuffle table. diff --git a/phpseclib/Crypt/EC.php b/phpseclib/Crypt/EC.php index 835d75fe..fb721d52 100644 --- a/phpseclib/Crypt/EC.php +++ b/phpseclib/Crypt/EC.php @@ -128,7 +128,7 @@ abstract class EC extends AsymmetricKey /** * @var string */ - protected $sigFormat; + protected $sigFormat = ''; /** * Create public / private key pair. @@ -174,7 +174,13 @@ abstract class EC extends AsymmetricKey $reflect->getShortName(); $curve = new $curve(); - $privatekey->dA = $dA = $curve->createRandomMultiplier(); + if ($curve instanceof TwistedEdwardsCurve) { + $arr = $curve->extractSecret(Random::string($curve instanceof Ed448 ? 57 : 32)); + $privatekey->dA = $dA = $arr['dA']; + $privatekey->secret = $arr['secret']; + } else { + $privatekey->dA = $dA = $curve->createRandomMultiplier(); + } if ($curve instanceof Curve25519 && self::$engines['libsodium']) { //$r = pack('H*', '0900000000000000000000000000000000000000000000000000000000000000'); //$QA = sodium_crypto_scalarmult($dA->toBytes(), $r); @@ -224,6 +230,7 @@ abstract class EC extends AsymmetricKey if (isset($components['dA'])) { $new->dA = $components['dA']; + $new->secret = $components['secret']; } if ($new->curve instanceof TwistedEdwardsCurve) { diff --git a/phpseclib/Crypt/EC/BaseCurves/KoblitzPrime.php b/phpseclib/Crypt/EC/BaseCurves/KoblitzPrime.php index 9d0a6d71..4454dcc6 100644 --- a/phpseclib/Crypt/EC/BaseCurves/KoblitzPrime.php +++ b/phpseclib/Crypt/EC/BaseCurves/KoblitzPrime.php @@ -40,6 +40,15 @@ use phpseclib3\Math\PrimeField; */ class KoblitzPrime extends Prime { + /** + * @var array> + */ + public $basis = []; + + /** + * @var object + */ + public $beta; // don't overwrite setCoefficients() with one that only accepts one parameter so that // one might be able to switch between KoblitzPrime and Prime more easily (for benchmarking // purposes). diff --git a/phpseclib/Crypt/EC/Curves/Ed25519.php b/phpseclib/Crypt/EC/Curves/Ed25519.php index 996c8294..fd467dea 100644 --- a/phpseclib/Crypt/EC/Curves/Ed25519.php +++ b/phpseclib/Crypt/EC/Curves/Ed25519.php @@ -157,7 +157,7 @@ class Ed25519 extends TwistedEdwards * * Used by the various key handlers * - * @return \phpseclib3\Math\PrimeField\Integer + * @return array */ public function extractSecret(string $str) { @@ -180,8 +180,10 @@ class Ed25519 extends TwistedEdwards // secret scalar s. $dA = new BigInteger($h, 256); - $dA->secret = $str; - return $dA; + return [ + 'dA' => $dA, + 'secret' => $str + ]; } /** @@ -205,7 +207,7 @@ class Ed25519 extends TwistedEdwards */ public function createRandomMultiplier(): BigInteger { - return $this->extractSecret(Random::string(32)); + return $this->extractSecret(Random::string(32))['dA']; } /** diff --git a/phpseclib/Crypt/EC/Curves/Ed448.php b/phpseclib/Crypt/EC/Curves/Ed448.php index c6590450..b0b0827a 100644 --- a/phpseclib/Crypt/EC/Curves/Ed448.php +++ b/phpseclib/Crypt/EC/Curves/Ed448.php @@ -97,7 +97,7 @@ class Ed448 extends TwistedEdwards * * Used by the various key handlers * - * @return \phpseclib3\Math\PrimeField\Integer + * @return array */ public function extractSecret(string $str) { @@ -121,8 +121,10 @@ class Ed448 extends TwistedEdwards // secret scalar s. $dA = new BigInteger($h, 256); - $dA->secret = $str; - return $dA; + return [ + 'dA' => $dA, + 'secret' => $str + ]; } /** @@ -145,7 +147,7 @@ class Ed448 extends TwistedEdwards */ public function createRandomMultiplier(): BigInteger { - return $this->extractSecret(Random::string(57)); + return $this->extractSecret(Random::string(57))['dA']; } /** diff --git a/phpseclib/Crypt/EC/Curves/secp160k1.php b/phpseclib/Crypt/EC/Curves/secp160k1.php index 02a461a5..6a4d273c 100644 --- a/phpseclib/Crypt/EC/Curves/secp160k1.php +++ b/phpseclib/Crypt/EC/Curves/secp160k1.php @@ -20,10 +20,6 @@ use phpseclib3\Math\BigInteger; class secp160k1 extends KoblitzPrime { - public $basis; - - public $beta; - public function __construct() { // same as secp160r2 diff --git a/phpseclib/Crypt/EC/Curves/secp192k1.php b/phpseclib/Crypt/EC/Curves/secp192k1.php index ee97b193..952c56e0 100644 --- a/phpseclib/Crypt/EC/Curves/secp192k1.php +++ b/phpseclib/Crypt/EC/Curves/secp192k1.php @@ -20,10 +20,6 @@ use phpseclib3\Math\BigInteger; class secp192k1 extends KoblitzPrime { - public $basis; - - public $beta; - public function __construct() { $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37', 16)); diff --git a/phpseclib/Crypt/EC/Curves/secp224k1.php b/phpseclib/Crypt/EC/Curves/secp224k1.php index f62df8cf..bf45dc82 100644 --- a/phpseclib/Crypt/EC/Curves/secp224k1.php +++ b/phpseclib/Crypt/EC/Curves/secp224k1.php @@ -20,10 +20,6 @@ use phpseclib3\Math\BigInteger; class secp224k1 extends KoblitzPrime { - public $basis; - - public $beta; - public function __construct() { $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D', 16)); diff --git a/phpseclib/Crypt/EC/Curves/secp256k1.php b/phpseclib/Crypt/EC/Curves/secp256k1.php index 6463727c..e886e592 100644 --- a/phpseclib/Crypt/EC/Curves/secp256k1.php +++ b/phpseclib/Crypt/EC/Curves/secp256k1.php @@ -24,10 +24,6 @@ use phpseclib3\Math\BigInteger; //class secp256k1 extends Prime class secp256k1 extends KoblitzPrime { - public $basis; - - public $beta; - public function __construct() { $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F', 16)); diff --git a/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php b/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php index bce9c257..15f94d2e 100644 --- a/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php +++ b/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php @@ -176,21 +176,22 @@ abstract class OpenSSH extends Progenitor BigInteger $privateKey, BaseCurve $curve, array $publicKey, - $password = '', + $password, + string $secret, array $options = [] ): string { if ($curve instanceof Ed25519) { - if (!isset($privateKey->secret)) { + if (!isset($secret)) { throw new \RuntimeException('Private Key does not have a secret set'); } - if (strlen($privateKey->secret) != 32) { + if (strlen($secret) != 32) { throw new \RuntimeException('Private Key secret is not of the correct length'); } $pubKey = $curve->encodePoint($publicKey); $publicKey = Strings::packSSH2('ss', 'ssh-ed25519', $pubKey); - $privateKey = Strings::packSSH2('sss', 'ssh-ed25519', $pubKey, $privateKey->secret . $pubKey); + $privateKey = Strings::packSSH2('sss', 'ssh-ed25519', $pubKey, $secret . $pubKey); return self::wrapPrivateKey($publicKey, $privateKey, $password, $options); } diff --git a/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php b/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php index 10477504..f00bb320 100644 --- a/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php +++ b/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php @@ -164,7 +164,7 @@ abstract class PKCS1 extends Progenitor * * @param Integer[] $publicKey */ - public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, ?string $password = null, array $options = []): string + public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, string $secret, ?string $password = null, array $options = []): string { self::initialize_static_variables(); diff --git a/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php b/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php index b1bb2df3..4b44e7dc 100644 --- a/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php +++ b/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php @@ -149,7 +149,9 @@ abstract class PKCS8 extends Progenitor if (substr($key['privateKey'], 0, 2) != "\x04\x20") { throw new \RuntimeException('The first two bytes of the private key field should be 0x0420'); } - $components['dA'] = $components['curve']->extractSecret(substr($key['privateKey'], 2)); + $arr = $components['curve']->extractSecret(substr($key['privateKey'], 2)); + $components['dA'] = $arr['dA']; + $components['secret'] = $arr['secret']; } if (isset($key['publicKey'])) { @@ -201,7 +203,7 @@ abstract class PKCS8 extends Progenitor * * @param Integer[] $publicKey */ - public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, ?string $password = null, array $options = []): string + public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, string $secret, ?string $password = null, array $options = []): string { self::initialize_static_variables(); @@ -211,7 +213,7 @@ abstract class PKCS8 extends Progenitor if ($curve instanceof TwistedEdwardsCurve) { return self::wrapPrivateKey( - "\x04\x20" . $privateKey->secret, + "\x04\x20" . $secret, [], null, $password, diff --git a/phpseclib/Crypt/EC/Formats/Keys/PuTTY.php b/phpseclib/Crypt/EC/Formats/Keys/PuTTY.php index 181a95d6..37cff288 100644 --- a/phpseclib/Crypt/EC/Formats/Keys/PuTTY.php +++ b/phpseclib/Crypt/EC/Formats/Keys/PuTTY.php @@ -73,7 +73,9 @@ abstract class PuTTY extends Progenitor if (Strings::shift($private, 4) != "\0\0\0\x20") { throw new \RuntimeException('Length of ssh-ed25519 key should be 32'); } - $components['dA'] = $components['curve']->extractSecret($private); + $arr = $components['curve']->extractSecret($private); + $components['dA'] = $arr['dA']; + $components['secret'] = $arr['secret']; } else { [$components['dA']] = Strings::unpackSSH2('i', $private); $components['curve']->rangeCheck($components['dA']); @@ -87,7 +89,7 @@ abstract class PuTTY extends Progenitor * * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey */ - public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, ?string $password = null, array $options = []): string + public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, string $secret, ?string $password = null, array $options = []): string { self::initialize_static_variables(); @@ -107,7 +109,7 @@ abstract class PuTTY extends Progenitor } $private = $curve instanceof TwistedEdwardsCurve ? - Strings::packSSH2('s', $privateKey->secret) : + Strings::packSSH2('s', $secret) : Strings::packSSH2('s', $private); return self::wrapPrivateKey($public, $private, $name, $password, $options); diff --git a/phpseclib/Crypt/EC/Formats/Keys/libsodium.php b/phpseclib/Crypt/EC/Formats/Keys/libsodium.php index 9ee1deb4..b32d0136 100644 --- a/phpseclib/Crypt/EC/Formats/Keys/libsodium.php +++ b/phpseclib/Crypt/EC/Formats/Keys/libsodium.php @@ -64,7 +64,9 @@ abstract class libsodium $curve = new Ed25519(); $components = ['curve' => $curve]; if (isset($private)) { - $components['dA'] = $curve->extractSecret($private); + $arr = $curve->extractSecret($private); + $components['dA'] = $arr['dA']; + $components['secret'] = $arr['secret']; } $components['QA'] = isset($public) ? self::extractPoint($public, $curve) : @@ -88,17 +90,17 @@ abstract class libsodium * * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey */ - public static function savePrivateKey(BigInteger $privateKey, Ed25519 $curve, array $publicKey, ?string $password = null): string + public static function savePrivateKey(BigInteger $privateKey, Ed25519 $curve, array $publicKey, string $secret, ?string $password = null): string { - if (!isset($privateKey->secret)) { + if (!isset($secret)) { throw new \RuntimeException('Private Key does not have a secret set'); } - if (strlen($privateKey->secret) != 32) { + if (strlen($secret) != 32) { throw new \RuntimeException('Private Key secret is not of the correct length'); } if (!empty($password) && is_string($password)) { throw new UnsupportedFormatException('libsodium private keys do not support encryption'); } - return $privateKey->secret . $curve->encodePoint($publicKey); + return $secret . $curve->encodePoint($publicKey); } } diff --git a/phpseclib/Crypt/EC/PrivateKey.php b/phpseclib/Crypt/EC/PrivateKey.php index f9991bf8..7eb5edda 100644 --- a/phpseclib/Crypt/EC/PrivateKey.php +++ b/phpseclib/Crypt/EC/PrivateKey.php @@ -46,6 +46,11 @@ class PrivateKey extends EC implements Common\PrivateKey */ protected $dA; + /** + * @var string + */ + protected $secret = ''; + /** * Multiplies an encoded point by the private key * @@ -110,7 +115,7 @@ class PrivateKey extends EC implements Common\PrivateKey $curve = $this->curve; $hash = new Hash($curve::HASH); - $secret = substr($hash->hash($this->dA->secret), $curve::SIZE); + $secret = substr($hash->hash($this->secret), $curve::SIZE); if ($curve instanceof Ed25519) { $dom = !isset($this->context) ? '' : @@ -213,7 +218,7 @@ class PrivateKey extends EC implements Common\PrivateKey { $type = self::validatePlugin('Keys', $type, 'savePrivateKey'); - return $type::savePrivateKey($this->dA, $this->curve, $this->QA, $this->password, $options); + return $type::savePrivateKey($this->dA, $this->curve, $this->QA, $this->password, $this->secret, $options); } /** diff --git a/phpseclib/Crypt/Hash.php b/phpseclib/Crypt/Hash.php index af270574..28ac5c4e 100644 --- a/phpseclib/Crypt/Hash.php +++ b/phpseclib/Crypt/Hash.php @@ -173,7 +173,7 @@ class Hash /** * @var int */ - private $blockSize; + private $blockSize = 0; /**#@+ * UMAC variables diff --git a/phpseclib/Crypt/RSA.php b/phpseclib/Crypt/RSA.php index 7f631805..323290f9 100644 --- a/phpseclib/Crypt/RSA.php +++ b/phpseclib/Crypt/RSA.php @@ -251,6 +251,16 @@ abstract class RSA extends AsymmetricKey */ private static $smallestPrime = 4096; + /** + * Public Exponent + */ + protected $publicExponent = false; + + /** + * Private Exponent + */ + protected $privateExponent = null; + /** * Sets the public exponent for key generation * diff --git a/phpseclib/Crypt/RSA/PrivateKey.php b/phpseclib/Crypt/RSA/PrivateKey.php index a7dcad6a..315500df 100644 --- a/phpseclib/Crypt/RSA/PrivateKey.php +++ b/phpseclib/Crypt/RSA/PrivateKey.php @@ -50,16 +50,6 @@ class PrivateKey extends RSA implements Common\PrivateKey */ protected $coefficients; - /** - * Public Exponent - */ - protected $publicExponent = false; - - /** - * Private Exponent - */ - protected $privateExponent; - /** * RSADP * diff --git a/phpseclib/Crypt/RSA/PublicKey.php b/phpseclib/Crypt/RSA/PublicKey.php index 0b9e39f2..c20f08fd 100644 --- a/phpseclib/Crypt/RSA/PublicKey.php +++ b/phpseclib/Crypt/RSA/PublicKey.php @@ -34,16 +34,6 @@ class PublicKey extends RSA implements Common\PublicKey { use Common\Traits\Fingerprint; - /** - * Public Exponent - */ - protected $publicExponent = false; - - /** - * Private Exponent - */ - protected $privateExponent; - /** * Exponentiate */ diff --git a/phpseclib/Math/BigInteger.php b/phpseclib/Math/BigInteger.php index 8b3e7e76..88860838 100644 --- a/phpseclib/Math/BigInteger.php +++ b/phpseclib/Math/BigInteger.php @@ -79,11 +79,6 @@ class BigInteger implements \JsonSerializable */ private $precision; - /** - * @var string - */ - public $secret; - /** * Sets engine type. * diff --git a/phpseclib/Math/BinaryField/Integer.php b/phpseclib/Math/BinaryField/Integer.php index 40750b22..b6bb12c8 100644 --- a/phpseclib/Math/BinaryField/Integer.php +++ b/phpseclib/Math/BinaryField/Integer.php @@ -62,11 +62,6 @@ class Integer extends Base */ protected static $reduce; - /** - * @var bool|string - */ - public $key; - /** * Default constructor */ diff --git a/phpseclib/Math/PrimeField.php b/phpseclib/Math/PrimeField.php index 0b49c517..4074a7e3 100644 --- a/phpseclib/Math/PrimeField.php +++ b/phpseclib/Math/PrimeField.php @@ -41,11 +41,6 @@ class PrimeField extends FiniteField */ protected $instanceID; - /** - * @var BigInteger - */ - protected $modulo; - /** * Default constructor */ @@ -55,8 +50,6 @@ class PrimeField extends FiniteField // throw new \UnexpectedValueException('PrimeField requires a prime number be passed to the constructor'); //} - $this->modulo = $modulo; - $this->instanceID = self::$instanceCounter++; Integer::setModulo($this->instanceID, $modulo); Integer::setRecurringModuloFunction($this->instanceID, $modulo->createRecurringModuloFunction()); diff --git a/tests/Unit/Crypt/EC/Ed448PrivateKey.php b/tests/Unit/Crypt/EC/Ed448PrivateKey.php index c5b8b0d6..ad97ee62 100644 --- a/tests/Unit/Crypt/EC/Ed448PrivateKey.php +++ b/tests/Unit/Crypt/EC/Ed448PrivateKey.php @@ -16,7 +16,9 @@ class Ed448PrivateKey } $components = ['curve' => new Ed448()]; - $components['dA'] = $components['curve']->extractSecret($key); + $arr = $components['curve']->extractSecret($key); + $components['dA'] = $arr['dA']; + $components['secret'] = $arr['secret']; $components['QA'] = $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']); return $components;