@ -1,7 +1,6 @@
< ? php
declare ( strict_types = 1 );
/**
* SPDX - FileCopyrightText : 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX - License - Identifier : AGPL - 3.0 - or - later
@ -16,6 +15,7 @@ use NCU\Security\Signature\Exceptions\InvalidSignatureException;
use NCU\Security\Signature\Exceptions\SignatoryConflictException ;
use NCU\Security\Signature\Exceptions\SignatoryException ;
use NCU\Security\Signature\Exceptions\SignatoryNotFoundException ;
use NCU\Security\Signature\Exceptions\SignatureElementNotFoundException ;
use NCU\Security\Signature\Exceptions\SignatureException ;
use NCU\Security\Signature\Exceptions\SignatureNotFoundException ;
use NCU\Security\Signature\ISignatoryManager ;
@ -45,7 +45,7 @@ use Psr\Log\LoggerInterface;
* " date " : " Mon, 08 Jul 2024 14:16:20 GMT " ,
* " digest " : " SHA-256=U7gNVUQiixe5BRbp4Tg0xCZMTcSWXXUZI2 \\ /xtHM40S0= " ,
* " host " : " hostname.of.the.recipient " ,
* " Signature " : " keyId= \" https://author.hostname/key \" ,algorithm= \" ras- sha256\" ,headers= \" content-length
* " Signature " : " keyId= \" https://author.hostname/key \" ,algorithm= \" sha256 \" ,headers= \" content-length
* date digest host\ " ,signature= \" DzN12OCS1rsA[...]o0VmxjQooRo6HHabg== \" "
* }
*
@ -66,11 +66,11 @@ use Psr\Log\LoggerInterface;
* @ since 31.0 . 0
*/
class SignatureManager implements ISignatureManager {
private const DATE_HEADER = 'D, d M Y H:i:s T' ;
private const DATE_TTL = 300 ;
private const SIGNATORY_TTL = 86400 * 3 ;
private const TABLE_SIGNATORIES = 'sec_signatory' ;
private const BODY_MAXSIZE = 50000 ; // max size of the payload of the request
public const DATE_HEADER = 'D, d M Y H:i:s T' ;
public const DATE_TTL = 300 ;
public const SIGNATORY_TTL = 86400 * 3 ;
public const TABLE_SIGNATORIES = 'sec_signatory' ;
public const BODY_MAXSIZE = 50000 ; // max size of the payload of the request
public const APPCONFIG_IDENTITY = 'security.signature.identity' ;
public function __construct (
@ -98,25 +98,29 @@ class SignatureManager implements ISignatureManager {
? string $body = null ,
) : IIncomingSignedRequest {
$body = $body ? ? file_get_contents ( 'php://input' );
if ( strlen ( $body ) > self :: BODY_MAXSIZE ) {
$options = $signatoryManager -> getOptions ();
if ( strlen ( $body ) > ( $options [ 'bodyMaxSize' ] ? ? self :: BODY_MAXSIZE )) {
throw new IncomingRequestException ( 'content of request is too big' );
}
$signedRequest = new IncomingSignedRequest ( $body );
$signedRequest -> setRequest ( $this -> request );
$options = $signatoryManager -> getOptions ();
// generate IncomingSignedRequest based on body and request
$signedRequest = new IncomingSignedRequest ( $body , $this -> request , $options );
try {
// we set origin based on the keyId defined in the Signature header of the request
$signedRequest -> setOrigin ( $this -> extractIdentityFromUri ( $signedRequest -> getSignatureElement ( 'keyId' )));
} catch ( IdentityNotFoundException $e ) {
throw new IncomingRequestException ( $e -> getMessage ());
}
try {
$this -> verifyIncomingRequestTime ( $signedRequest , $options [ 'ttl' ] ? ? self :: DATE_TTL );
$this -> verifyIncomingRequestContent ( $signedRequest );
$this -> prepIncomingSignatureHeader ( $signedRequest );
$this -> verifyIncomingSignatureHeader ( $signedRequest );
$this -> prepEstimatedSignature ( $signedRequest , $options [ 'extraSignatureHeaders' ] ? ? []);
$this -> verifyIncomingRequestSignature ( $signedRequest , $signatoryManager , $options [ 'ttlSignatory' ] ? ? self :: SIGNATORY_TTL );
// confirm the validity of content and identity of the incoming request
$this -> generateExpectedClearSignatureFromRequest ( $signedRequest , $options [ 'extraSignatureHeaders' ] ? ? []);
$this -> confirmIncomingRequestSignature ( $signedRequest , $signatoryManager , $options [ 'ttlSignatory' ] ? ? self :: SIGNATORY_TTL );
} catch ( SignatureException $e ) {
$this -> logger -> warning (
'signature could not be verified' , [
'exception' => $e , 'signedRequest' => $signedRequest ,
'exception' => $e ,
'signedRequest' => $signedRequest ,
'signatoryManager' => get_class ( $signatoryManager )
]
);
@ -126,6 +130,95 @@ class SignatureManager implements ISignatureManager {
return $signedRequest ;
}
/**
* generating the expected signature ( clear version ) sent by the remote instance
* based on the data available in the Signature header .
*
* @ param IIncomingSignedRequest $signedRequest
* @ param array $extraSignatureHeaders
*
* @ throws SignatureException
*/
private function generateExpectedClearSignatureFromRequest (
IIncomingSignedRequest $signedRequest ,
array $extraSignatureHeaders = [],
) : void {
$request = $signedRequest -> getRequest ();
$usedHeaders = explode ( ' ' , $signedRequest -> getSignatureElement ( 'headers' ));
$neededHeaders = array_merge ([ 'date' , 'host' , 'content-length' , 'digest' ], array_keys ( $extraSignatureHeaders ));
$missingHeaders = array_diff ( $neededHeaders , $usedHeaders );
if ( $missingHeaders !== []) {
throw new SignatureException ( 'missing entries in Signature.headers: ' . json_encode ( $missingHeaders ));
}
$estimated = [ '(request-target): ' . strtolower ( $request -> getMethod ()) . ' ' . $request -> getRequestUri ()];
foreach ( $usedHeaders as $key ) {
if ( $key === '(request-target)' ) {
continue ;
}
$value = ( strtolower ( $key ) === 'host' ) ? $request -> getServerHost () : $request -> getHeader ( $key );
if ( $value === '' ) {
throw new SignatureException ( 'missing header ' . $key . ' in request' );
}
$estimated [] = $key . ': ' . $value ;
}
$signedRequest -> setClearSignature ( implode ( " \n " , $estimated ));
}
/**
* confirm that the Signature is signed using the correct private key , using
* clear version of the Signature and the public key linked to the keyId
*
* @ param IIncomingSignedRequest $signedRequest
* @ param ISignatoryManager $signatoryManager
*
* @ throws SignatoryNotFoundException
* @ throws SignatureException
*/
private function confirmIncomingRequestSignature (
IIncomingSignedRequest $signedRequest ,
ISignatoryManager $signatoryManager ,
int $ttlSignatory ,
) : void {
$knownSignatory = null ;
try {
$knownSignatory = $this -> getStoredSignatory ( $signedRequest -> getKeyId ());
// refreshing ttl and compare with previous public key
if ( $ttlSignatory > 0 && $knownSignatory -> getLastUpdated () < ( time () - $ttlSignatory )) {
$signatory = $this -> getSaneRemoteSignatory ( $signatoryManager , $signedRequest );
$this -> updateSignatoryMetadata ( $signatory );
$knownSignatory -> setMetadata ( $signatory -> getMetadata ());
}
$signedRequest -> setSignatory ( $knownSignatory );
$this -> verifySignedRequest ( $signedRequest );
} catch ( InvalidKeyOriginException $e ) {
throw $e ; // issue while requesting remote instance also means there is no 2nd try
} catch ( SignatoryNotFoundException ) {
// if no signatory in cache, we retrieve the one from the remote instance (using
// $signatoryManager), check its validity with current signature and store it
$signatory = $this -> getSaneRemoteSignatory ( $signatoryManager , $signedRequest );
$signedRequest -> setSignatory ( $signatory );
$this -> verifySignedRequest ( $signedRequest );
$this -> storeSignatory ( $signatory );
} catch ( SignatureException ) {
// if public key (from cache) is not valid, we try to refresh it (based on SignatoryType)
try {
$signatory = $this -> getSaneRemoteSignatory ( $signatoryManager , $signedRequest );
} catch ( SignatoryNotFoundException $e ) {
$this -> manageDeprecatedSignatory ( $knownSignatory );
throw $e ;
}
$signedRequest -> setSignatory ( $signatory );
$this -> verifySignedRequest ( $signedRequest );
$this -> storeSignatory ( $signatory );
}
}
/**
* @ inheritDoc
*
@ -135,6 +228,9 @@ class SignatureManager implements ISignatureManager {
* @ param string $uri needed in the signature
*
* @ return IOutgoingSignedRequest
* @ throws IdentityNotFoundException
* @ throws SignatoryException
* @ throws SignatoryNotFoundException
* @ since 31.0 . 0
*/
public function getOutgoingSignedRequest (
@ -143,26 +239,43 @@ class SignatureManager implements ISignatureManager {
string $method ,
string $uri ,
) : IOutgoingSignedRequest {
$signedRequest = new OutgoingSignedRequest ( $content );
$options = $signatoryManager -> getOptions ();
$signedRequest -> setHost ( $this -> getHostFromUri ( $uri ))
-> setAlgorithm ( $options [ 'algorithm' ] ? ? 'sha256' )
-> setSignatory ( $signatoryManager -> getLocalSignatory ());
$this -> setOutgoingSignatureHeader (
$signedRequest ,
strtolower ( $method ),
parse_url ( $uri , PHP_URL_PATH ) ? ? '/' ,
$options [ 'dateHeader' ] ? ? self :: DATE_HEADER
$signedRequest = new OutgoingSignedRequest (
$content ,
$signatoryManager ,
$this -> extractIdentityFromUri ( $uri ),
$method ,
parse_url ( $uri , PHP_URL_PATH ) ? ? '/'
);
$this -> setOutgoingClearSignature ( $signedRequest );
$this -> setOutgoingSignedSignature ( $signedRequest );
$this -> signingOutgoingRequest ( $signedRequest );
$this -> signOutgoingRequest ( $signedRequest );
return $signedRequest ;
}
/**
* signing clear version of the Signature header
*
* @ param IOutgoingSignedRequest $signedRequest
*
* @ throws SignatoryException
* @ throws SignatoryNotFoundException
*/
private function signOutgoingRequest ( IOutgoingSignedRequest $signedRequest ) : void {
$clear = $signedRequest -> getClearSignature ();
$signed = $this -> signString ( $clear , $signedRequest -> getSignatory () -> getPrivateKey (), $signedRequest -> getAlgorithm ());
$signatory = $signedRequest -> getSignatory ();
$signatureElements = [
'keyId="' . $signatory -> getKeyId () . '"' ,
'algorithm="' . $signedRequest -> getAlgorithm () -> value . '"' ,
'headers="' . implode ( ' ' , $signedRequest -> getHeaderList ()) . '"' ,
'signature="' . $signed . '"'
];
$signedRequest -> setSignedSignature ( $signed );
$signedRequest -> addHeader ( 'Signature' , implode ( ',' , $signatureElements ));
}
/**
* @ inheritDoc
*
@ -267,292 +380,36 @@ class SignatureManager implements ISignatureManager {
}
/**
* using the requested 'date' entry from header to confirm request is not older than ttl
*
* @ param IIncomingSignedRequest $signedRequest
* @ param int $ttl
*
* @ throws IncomingRequestException
* @ throws SignatureNotFoundException
*/
private function verifyIncomingRequestTime ( IIncomingSignedRequest $signedRequest , int $ttl ) : void {
$request = $signedRequest -> getRequest ();
$date = $request -> getHeader ( 'date' );
if ( $date === '' ) {
throw new SignatureNotFoundException ( 'missing date in header' );
}
try {
$dTime = new \DateTime ( $date );
$signedRequest -> setTime ( $dTime -> getTimestamp ());
} catch ( \Exception $e ) {
$this -> logger -> warning (
'datetime exception' , [ 'exception' => $e , 'header' => $request -> getHeader ( 'date' )]
);
throw new IncomingRequestException ( 'datetime exception' );
}
if ( $signedRequest -> getTime () < ( time () - $ttl )) {
throw new IncomingRequestException ( 'object is too old' );
}
}
/**
* confirm the values of 'content-length' and 'digest' from header
* is related to request content
*
* @ param IIncomingSignedRequest $signedRequest
*
* @ throws IncomingRequestException
* @ throws SignatureNotFoundException
*/
private function verifyIncomingRequestContent ( IIncomingSignedRequest $signedRequest ) : void {
$request = $signedRequest -> getRequest ();
$contentLength = $request -> getHeader ( 'content-length' );
if ( $contentLength === '' ) {
throw new SignatureNotFoundException ( 'missing content-length in header' );
}
if ( strlen ( $signedRequest -> getBody ()) !== ( int ) $request -> getHeader ( 'content-length' )) {
throw new IncomingRequestException (
'inexact content-length in header: ' . strlen ( $signedRequest -> getBody ()) . ' vs '
. ( int ) $request -> getHeader ( 'content-length' )
);
}
$digest = $request -> getHeader ( 'digest' );
if ( $digest === '' ) {
throw new SignatureNotFoundException ( 'missing digest in header' );
}
if ( $digest !== $signedRequest -> getDigest ()) {
throw new IncomingRequestException ( 'invalid value for digest in header' );
}
}
/**
* preparing a clear version of the signature based on list of metadata from the
* Signature entry in header
*
* @ param IIncomingSignedRequest $signedRequest
*
* @ throws SignatureNotFoundException
*/
private function prepIncomingSignatureHeader ( IIncomingSignedRequest $signedRequest ) : void {
$sign = [];
$request = $signedRequest -> getRequest ();
$signature = $request -> getHeader ( 'Signature' );
if ( $signature === '' ) {
throw new SignatureNotFoundException ( 'missing Signature in header' );
}
foreach ( explode ( ',' , $signature ) as $entry ) {
if ( $entry === '' || ! strpos ( $entry , '=' )) {
continue ;
}
[ $k , $v ] = explode ( '=' , $entry , 2 );
preg_match ( '/"([^"]+)"/' , $v , $var );
if ( $var [ 0 ] !== '' ) {
$v = trim ( $var [ 0 ], '"' );
}
$sign [ $k ] = $v ;
}
$signedRequest -> setSignatureHeader ( $sign );
}
/**
* @ param IIncomingSignedRequest $signedRequest
*
* @ throws IncomingRequestException
* @ throws InvalidKeyOriginException
*/
private function verifyIncomingSignatureHeader ( IIncomingSignedRequest $signedRequest ) : void {
$data = $signedRequest -> getSignatureHeader ();
if ( ! array_key_exists ( 'keyId' , $data ) || ! array_key_exists ( 'headers' , $data )
|| ! array_key_exists ( 'signature' , $data )) {
throw new IncomingRequestException ( 'missing keys in signature headers: ' . json_encode ( $data ));
}
try {
$signedRequest -> setOrigin ( $this -> getHostFromUri ( $data [ 'keyId' ]));
} catch ( \Exception ) {
throw new InvalidKeyOriginException ( 'cannot retrieve origin from ' . $data [ 'keyId' ]);
}
$signedRequest -> setSignedSignature ( $data [ 'signature' ]);
}
/**
* @ param IIncomingSignedRequest $signedRequest
* @ param array $extraSignatureHeaders
*
* @ throws IncomingRequestException
*/
private function prepEstimatedSignature (
IIncomingSignedRequest $signedRequest ,
array $extraSignatureHeaders = [],
) : void {
$request = $signedRequest -> getRequest ();
$headers = explode ( ' ' , $signedRequest -> getSignatureHeader ()[ 'headers' ] ? ? []);
$enforceHeaders = array_merge (
[ 'date' , 'host' , 'content-length' , 'digest' ],
$extraSignatureHeaders
);
$missingHeaders = array_diff ( $enforceHeaders , $headers );
if ( $missingHeaders !== []) {
throw new IncomingRequestException (
'missing elements in headers: ' . json_encode ( $missingHeaders )
);
}
$target = strtolower ( $request -> getMethod ()) . ' ' . $request -> getRequestUri ();
$estimated = [ '(request-target): ' . $target ];
foreach ( $headers as $key ) {
$value = $request -> getHeader ( $key );
if ( strtolower ( $key ) === 'host' ) {
$value = $request -> getServerHost ();
}
if ( $value === '' ) {
throw new IncomingRequestException ( 'empty elements in header ' . $key );
}
$estimated [] = $key . ': ' . $value ;
}
$signedRequest -> setEstimatedSignature ( implode ( " \n " , $estimated ));
}
/**
* @ param IIncomingSignedRequest $signedRequest
* @ param ISignatoryManager $signatoryManager
* get remote signatory using the ISignatoryManager
* and confirm the validity of the keyId
*
* @ throws SignatoryNotFoundException
* @ throws SignatureException
*/
private function verifyIncomingRequestSignature (
IIncomingSignedRequest $signedRequest ,
ISignatoryManager $signatoryManager ,
int $ttlSignatory ,
) : void {
$knownSignatory = null ;
try {
$knownSignatory = $this -> getStoredSignatory ( $signedRequest -> getKeyId ());
if ( $ttlSignatory > 0 && $knownSignatory -> getLastUpdated () < ( time () - $ttlSignatory )) {
$signatory = $this -> getSafeRemoteSignatory ( $signatoryManager , $signedRequest );
$this -> updateSignatoryMetadata ( $signatory );
$knownSignatory -> setMetadata ( $signatory -> getMetadata ());
}
$signedRequest -> setSignatory ( $knownSignatory );
$this -> verifySignedRequest ( $signedRequest );
} catch ( InvalidKeyOriginException $e ) {
throw $e ; // issue while requesting remote instance also means there is no 2nd try
} catch ( SignatoryNotFoundException | SignatureException ) {
try {
$signatory = $this -> getSafeRemoteSignatory ( $signatoryManager , $signedRequest );
} catch ( SignatoryNotFoundException $e ) {
$this -> manageDeprecatedSignatory ( $knownSignatory );
throw $e ;
}
$signedRequest -> setSignatory ( $signatory );
$this -> storeSignatory ( $signatory );
$this -> verifySignedRequest ( $signedRequest );
}
}
/**
* @ param ISignatoryManager $signatoryManager
* @ param IIncomingSignedRequest $signedRequest
*
* @ return ISignatory
* @ throws InvalidKeyOriginException
* @ throws SignatoryNotFoundException
* @ see ISignatoryManager :: getRemoteSignatory
*/
private function getSaf eRemoteSignatory (
private function getSaneRemoteSignatory (
ISignatoryManager $signatoryManager ,
IIncomingSignedRequest $signedRequest ,
) : ISignatory {
$signatory = $signatoryManager -> getRemoteSignatory ( $signedRequest );
$signatory = $signatoryManager -> getRemoteSignatory ( $signedRequest -> getOrigin ());
if ( $signatory === null ) {
throw new SignatoryNotFoundException ( 'empty result from getRemoteSignatory' );
}
if ( $signatory -> getKeyId () !== $signedRequest -> getKeyId ()) {
throw new InvalidKeyOriginException ( 'keyId from signatory not related to the one from request' );
}
return $signatory -> setProviderId ( $signatoryManager -> getProviderId ());
}
private function setOutgoingSignatureHeader (
IOutgoingSignedRequest $signedRequest ,
string $method ,
string $path ,
string $dateHeader ,
) : void {
$header = [
'(request-target)' => $method . ' ' . $path ,
'content-length' => strlen ( $signedRequest -> getBody ()),
'date' => gmdate ( $dateHeader ),
'digest' => $signedRequest -> getDigest (),
'host' => $signedRequest -> getHost ()
];
$signedRequest -> setSignatureHeader ( $header );
}
/**
* @ param IOutgoingSignedRequest $signedRequest
*/
private function setOutgoingClearSignature ( IOutgoingSignedRequest $signedRequest ) : void {
$signing = [];
$header = $signedRequest -> getSignatureHeader ();
foreach ( array_keys ( $header ) as $element ) {
$value = $header [ $element ];
$signing [] = $element . ': ' . $value ;
if ( $element !== '(request-target)' ) {
$signedRequest -> addHeader ( $element , $value );
try {
if ( $signatory -> getKeyId () !== $signedRequest -> getKeyId ()) {
throw new InvalidKeyOriginException ( 'keyId from signatory not related to the one from request' );
}
} catch ( SignatureElementNotFoundException ) {
throw new InvalidKeyOriginException ( 'missing keyId' );
}
$signedRequest -> setClearSignature ( implode ( " \n " , $signing ));
}
private function setOutgoingSignedSignature ( IOutgoingSignedRequest $signedRequest ) : void {
$clear = $signedRequest -> getClearSignature ();
$signed = $this -> signString (
$clear , $signedRequest -> getSignatory () -> getPrivateKey (), $signedRequest -> getAlgorithm ()
);
$signedRequest -> setSignedSignature ( $signed );
}
private function signingOutgoingRequest ( IOutgoingSignedRequest $signedRequest ) : void {
$signatureHeader = $signedRequest -> getSignatureHeader ();
$headers = array_diff ( array_keys ( $signatureHeader ), [ '(request-target)' ]);
$signatory = $signedRequest -> getSignatory ();
$signatureElements = [
'keyId="' . $signatory -> getKeyId () . '"' ,
'algorithm="' . $this -> getChosenEncryption ( $signedRequest -> getAlgorithm ()) . '"' ,
'headers="' . implode ( ' ' , $headers ) . '"' ,
'signature="' . $signedRequest -> getSignedSignature () . '"'
];
$signedRequest -> addHeader ( 'Signature' , implode ( ',' , $signatureElements ));
return $signatory -> setProviderId ( $signatoryManager -> getProviderId ());
}
/**
* @ param IIncomingSignedRequest $signedRequest
*
@ -568,10 +425,10 @@ class SignatureManager implements ISignatureManager {
try {
$this -> verifyString (
$signedRequest -> getEstimated Signature (),
$signedRequest -> getClear Signature (),
$signedRequest -> getSignedSignature (),
$publicKey ,
$this -> getUsedEncryption ( $signedRequest )
SignatureAlgorithm :: tryFrom ( $signedRequest -> getSignatureElement ( 'algorithm' )) ? ? SignatureAlgorithm :: SHA256
);
} catch ( InvalidSignatureException $e ) {
$this -> logger -> debug ( 'signature issue' , [ 'signed' => $signedRequest , 'exception' => $e ]);
@ -579,45 +436,20 @@ class SignatureManager implements ISignatureManager {
}
}
private function getUsedEncryption ( IIncomingSignedRequest $signedRequest ) : SignatureAlgorithm {
$data = $signedRequest -> getSignatureHeader ();
return match ( $data [ 'algorithm' ]) {
'rsa-sha512' => SignatureAlgorithm :: SHA512 ,
default => SignatureAlgorithm :: SHA256 ,
};
}
private function getChosenEncryption ( string $algorithm ) : string {
return match ( $algorithm ) {
'sha512' => 'ras-sha512' ,
default => 'ras-sha256' ,
};
}
public function getOpenSSLAlgo ( string $algorithm ) : int {
return match ( $algorithm ) {
'sha512' => OPENSSL_ALGO_SHA512 ,
default => OPENSSL_ALGO_SHA256 ,
};
}
/**
* @ param string $clear
* @ param string $privateKey
* @ param string $algorithm
* @ param SignatureAlgorithm $algorithm
*
* @ return string
* @ throws SignatoryException
*/
private function signString ( string $clear , string $privateKey , string $algorithm ) : string {
private function signString ( string $clear , string $privateKey , SignatureAlgorithm $algorithm ) : string {
if ( $privateKey === '' ) {
throw new SignatoryException ( 'empty private key' );
}
openssl_sign ( $clear , $signed , $privateKey , $this -> getOpenSSLAlgo ( $algorithm ) );
openssl_sign ( $clear , $signed , $privateKey , $algorithm -> value );
return base64_encode ( $signed );
}
@ -626,19 +458,18 @@ class SignatureManager implements ISignatureManager {
* @ param string $clear
* @ param string $encoded
* @ param string $publicKey
* @ param SignatureAlgorithm $algo
* @ param SignatureAlgorithm $algorithm
*
* @ return void
* @ throws InvalidSignatureException
*/
private function verifyString (
string $clear ,
string $encoded ,
string $publicKey ,
SignatureAlgorithm $algo = SignatureAlgorithm :: SHA256 ,
SignatureAlgorithm $algorithm = SignatureAlgorithm :: SHA256 ,
) : void {
$signed = base64_decode ( $encoded );
if ( openssl_verify ( $clear , $signed , $publicKey , $algo -> value ) !== 1 ) {
if ( openssl_verify ( $clear , $signed , $publicKey , $algorithm -> value ) !== 1 ) {
throw new InvalidSignatureException ( 'signature issue' );
}
}
@ -692,11 +523,15 @@ class SignatureManager implements ISignatureManager {
}
}
/**
* @ param ISignatory $signatory
* @ throws DBException
*/
private function insertSignatory ( ISignatory $signatory ) : void {
$qb = $this -> connection -> getQueryBuilder ();
$qb -> insert ( self :: TABLE_SIGNATORIES )
-> setValue ( 'provider_id' , $qb -> createNamedParameter ( $signatory -> getProviderId ()))
-> setValue ( 'host' , $qb -> createNamedParameter ( $this -> getHost FromUri( $signatory -> getKeyId ())))
-> setValue ( 'host' , $qb -> createNamedParameter ( $this -> extractIdentity FromUri( $signatory -> getKeyId ())))
-> setValue ( 'account' , $qb -> createNamedParameter ( $signatory -> getAccount ()))
-> setValue ( 'key_id' , $qb -> createNamedParameter ( $signatory -> getKeyId ()))
-> setValue ( 'key_id_sum' , $qb -> createNamedParameter ( $this -> hashKeyId ( $signatory -> getKeyId ())))
@ -755,12 +590,12 @@ class SignatureManager implements ISignatureManager {
case SignatoryType :: REFRESHABLE :
// TODO: send notice to admin
throw new SignatoryConflictException ();
throw new SignatoryConflictException (); // while it can be refreshed, it must exist
case SignatoryType :: TRUSTED :
case SignatoryType :: STATIC :
// TODO: send warning to admin
throw new SignatoryConflictException ();
throw new SignatoryConflictException (); // no way.
}
}
@ -796,27 +631,6 @@ class SignatureManager implements ISignatureManager {
$qb -> executeStatement ();
}
/**
* @ param string $uri
*
* @ return string
* @ throws InvalidKeyOriginException
*/
private function getHostFromUri ( string $uri ) : string {
$host = parse_url ( $uri , PHP_URL_HOST );
$port = parse_url ( $uri , PHP_URL_PORT );
if ( $port !== null && $port !== false ) {
$host .= ':' . $port ;
}
if ( is_string ( $host ) && $host !== '' ) {
return $host ;
}
throw new \Exception ( 'invalid/empty uri' );
}
private function hashKeyId ( string $keyId ) : string {
return hash ( 'sha256' , $keyId );
}