/// <summary> /// Calculates a private key from a secret. /// </summary> /// <param name="Secret">Binary secret.</param> /// <returns>Private key</returns> public override Tuple <byte[], byte[]> CalculatePrivateKey(byte[] Secret) { byte[] Bin = Secret; switch (Bin.Length) { case 56: Array.Resize <byte>(ref Bin, 57); break; case 57: break; default: Bin = Hashes.ComputeSHA512Hash(Secret); Array.Resize <byte>(ref Bin, 57); break; } Bin[0] &= 0xfc; Bin[55] |= 0x80; Bin[56] |= 0; return(new Tuple <byte[], byte[]>(Bin, null)); }
/// <summary> /// Evaluates the function on a scalar argument. /// </summary> /// <param name="Argument">Function argument.</param> /// <param name="Variables">Variables collection.</param> /// <returns>Function result.</returns> public override IElement EvaluateScalar(IElement Argument, Variables Variables) { if (!(Argument.AssociatedObjectValue is byte[] Bin)) { throw new ScriptRuntimeException("Binary data expected.", this); } return(new ObjectValue(Hashes.ComputeSHA512Hash(Bin))); }
/// <summary> /// Executes a method on the resource. The default behaviour is to call the corresponding execution methods defined in the specialized /// interfaces <see cref="IHttpGetMethod"/>, <see cref="IHttpPostMethod"/>, <see cref="IHttpPutMethod"/> and <see cref="IHttpDeleteMethod"/> /// if they are defined for the resource. /// </summary> /// <param name="Server">HTTP Server</param> /// <param name="Request">HTTP Request</param> /// <param name="Response">HTTP Response</param> /// <exception cref="HttpException">If an error occurred when processing the method.</exception> public virtual async Task Execute(HttpServer Server, HttpRequest Request, HttpResponse Response) { HttpRequestHeader Header = Request.Header; string Method = Request.Header.Method; if (this.UserSessions && Request.Session is null) { HttpFieldCookie Cookie; string HttpSessionID; if ((Cookie = Request.Header.Cookie) is null || string.IsNullOrEmpty(HttpSessionID = Cookie["HttpSessionID"])) { HttpSessionID = Convert.ToBase64String(Hashes.ComputeSHA512Hash(Guid.NewGuid().ToByteArray())); Response.SetCookie(new Cookie("HttpSessionID", HttpSessionID, null, "/", null, false, true)); } Request.Session = Server.GetSession(HttpSessionID); } switch (Method) { case "GET": case "HEAD": if (!(this.getRanges is null)) { Response.SetHeader("Accept-Ranges", "bytes"); if (Header.Range != null) { ByteRangeInterval FirstInterval = Header.Range.FirstInterval; if (FirstInterval is null) { throw new RangeNotSatisfiableException(); } else { Response.OnlyHeader = Method == "HEAD"; Response.StatusCode = 206; Response.StatusMessage = "Partial Content"; await this.getRanges.GET(Request, Response, FirstInterval); } } else { Response.OnlyHeader = Method == "HEAD"; if (!(this.get is null)) { await this.get.GET(Request, Response); }
/// <summary> /// Calculates a private key from a secret. /// </summary> /// <param name="Secret">Binary secret.</param> /// <returns>Private key</returns> public override Tuple <byte[], byte[]> CalculatePrivateKey(byte[] Secret) { byte[] Bin = Hashes.ComputeSHA512Hash(Secret); byte[] AdditionalInfo = new byte[32]; byte[] PrivateKey = new byte[32]; if (this.hashSecret) { Array.Copy(Bin, 0, PrivateKey, 0, 32); } else { Array.Copy(Secret, 0, PrivateKey, 0, Math.Min(32, Secret.Length)); } Array.Copy(Bin, 32, AdditionalInfo, 0, 32); PrivateKey[0] &= 0xf8; PrivateKey[31] &= 0x3f; PrivateKey[31] |= 0x40; return(new Tuple <byte[], byte[]>(PrivateKey, AdditionalInfo)); }
/// <summary> /// Executes a method on the resource. The default behaviour is to call the corresponding execution methods defined in the specialized /// interfaces <see cref="IHttpGetMethod"/>, <see cref="IHttpPostMethod"/>, <see cref="IHttpPutMethod"/> and <see cref="IHttpDeleteMethod"/> /// if they are defined for the resource. /// </summary> /// <param name="Server">HTTP Server</param> /// <param name="Request">HTTP Request</param> /// <param name="Response">HTTP Response</param> /// <exception cref="HttpException">If an error occurred when processing the method.</exception> public virtual void Execute(HttpServer Server, HttpRequest Request, HttpResponse Response) { HttpRequestHeader Header = Request.Header; string Method = Request.Header.Method; if (this.UserSessions) { HttpFieldCookie Cookie; string HttpSessionID; if ((Cookie = Request.Header.Cookie) is null || string.IsNullOrEmpty(HttpSessionID = Cookie["HttpSessionID"])) { HttpSessionID = System.Convert.ToBase64String(Hashes.ComputeSHA512Hash(Guid.NewGuid().ToByteArray())); Response.SetCookie(new HTTP.Cookie("HttpSessionID", HttpSessionID, null, "/", null, false, true)); } Request.Session = Server.GetSession(HttpSessionID); } switch (Method) { case "GET": case "HEAD": if (this.getRanges != null) { Response.SetHeader("Accept-Ranges", "bytes"); if (Header.Range != null) { ByteRangeInterval FirstInterval = Header.Range.FirstInterval; if (FirstInterval is null) { throw new RangeNotSatisfiableException(); } else { Response.OnlyHeader = Method == "HEAD"; Response.StatusCode = 206; Response.StatusMessage = "Partial Content"; this.getRanges.GET(Request, Response, FirstInterval); } } else { Response.OnlyHeader = Method == "HEAD"; if (this.get != null) { this.get.GET(Request, Response); } else { this.getRanges.GET(Request, Response, new ByteRangeInterval(0, null)); } } } else if (this.get != null) { Response.OnlyHeader = Method == "HEAD"; this.get.GET(Request, Response); } else { throw new MethodNotAllowedException(this.allowedMethods); } break; case "POST": if (this.postRanges != null) { if (Header.ContentRange != null) { ContentByteRangeInterval Interval = Header.ContentRange.Interval; if (Interval is null) { throw new RangeNotSatisfiableException(); } else { this.postRanges.POST(Request, Response, Interval); } } else { if (this.post != null) { this.post.POST(Request, Response); } else { long Total; if (Header.ContentLength != null) { Total = Header.ContentLength.ContentLength; } else if (Request.DataStream != null) { Total = Request.DataStream.Position; } else { Total = 0; } this.postRanges.POST(Request, Response, new ContentByteRangeInterval(0, Total - 1, Total)); } } } else if (this.post != null) { this.post.POST(Request, Response); } else { throw new MethodNotAllowedException(this.allowedMethods); } break; case "PUT": if (this.putRanges != null) { if (Header.ContentRange != null) { ContentByteRangeInterval Interval = Header.ContentRange.Interval; if (Interval is null) { throw new RangeNotSatisfiableException(); } else { this.putRanges.PUT(Request, Response, Interval); } } else { if (this.put != null) { this.put.PUT(Request, Response); } else { long Total; if (Header.ContentLength != null) { Total = Header.ContentLength.ContentLength; } else if (Request.DataStream != null) { Total = Request.DataStream.Position; } else { Total = 0; } this.putRanges.PUT(Request, Response, new ContentByteRangeInterval(0, Total - 1, Total)); } } } else if (this.put != null) { this.put.PUT(Request, Response); } else { throw new MethodNotAllowedException(this.allowedMethods); } break; case "DELETE": if (this.delete is null) { throw new MethodNotAllowedException(this.allowedMethods); } else { this.delete.DELETE(Request, Response); } break; case "OPTIONS": if (this.options is null) { throw new MethodNotAllowedException(this.allowedMethods); } else { this.options.OPTIONS(Request, Response); } break; case "TRACE": if (this.trace is null) { throw new MethodNotAllowedException(this.allowedMethods); } else { this.trace.TRACE(Request, Response); } break; default: throw new MethodNotAllowedException(this.allowedMethods); } if (this.Synchronous) { Response.SendResponse(); Response.Dispose(); } }