Ejemplo n.º 1
0
        public void AddReviewerAddressToReviewerStore(PublicReviewerAddressModel pra)
        {
            this.logger.LogTrace("({0}:'{1}',{2}:'{3}',{4}:{5})", nameof(pra.GroupId), pra.GroupId,
                                 nameof(pra.Address), pra.Address, nameof(pra.Network), pra.Network);

            if (!this.ReviewerAddresses.ContainsKey(pra.Address.ToString()))
            {
                this.logger.LogTrace("Reviewer address '{0}' was not found in the reviewer address store, adding it.", pra.Address);

                if (!String.IsNullOrEmpty(pra.GroupId))
                {
                    var existingGroup = this.ReviewerAddresses.Values.FirstOrDefault(ra => ra.GroupId == pra.GroupId);
                    if (existingGroup != null)
                    {
                        // let's use the same name for the same groupIds for every entry
                        pra.GroupName = existingGroup.GroupName;
                    }
                }
                else if (!String.IsNullOrWhiteSpace(pra.GroupName))
                {
                    var existingGroup = this.ReviewerAddresses.Values.FirstOrDefault(ra => ra.GroupName == pra.GroupName);
                    if (existingGroup != null)
                    {
                        pra.GroupId = existingGroup.GroupId;
                    }
                    else
                    {
                        // we have to generate an ID for this new group
                        pra.GroupId = new Key().ToHex(this.network);
                    }
                }

                this.ReviewerAddresses.Add(pra.Address, pra);

                SaveReviewerAddresses();
            }
            else
            {
                this.logger.LogTrace("Reviewer address '{0}' was already in the reviewer address store, skipping it.", pra.Address);
            }

            this.logger.LogTrace("(-)");
        }
Ejemplo n.º 2
0
        public IActionResult CreateReviewerAddressAsync([FromBody] CreateReviewerAddressRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // checks the request is valid
            if (!this.ModelState.IsValid)
            {
                return(ModelStateErrors.BuildErrorResponse(this.ModelState));
            }

            try
            {
                // calculate the Manager password hash
                byte[] binaryPassword = System.Text.Encoding.ASCII.GetBytes(request.RsaPassword);

                Org.BouncyCastle.Crypto.Digests.Sha512Digest sha = new Org.BouncyCastle.Crypto.Digests.Sha512Digest();
                sha.BlockUpdate(binaryPassword, 0, binaryPassword.Length);

                byte[] shaOutput = new byte[512 / 8];
                sha.DoFinal(shaOutput, 0);

                NBitcoin.DataEncoders.HexEncoder he = new NBitcoin.DataEncoders.HexEncoder();
                string rsaPasswordHashHex           = he.EncodeData(shaOutput);

                // create the multisig address
                PubKey[] groupMemberKeys = request.SignaturePubKeys.Select(pubKeyHex => new PubKey(pubKeyHex)).ToArray();

                var scriptPubKey = PayToMultiSigTemplate
                                   .Instance
                                   .GenerateScriptPubKey(request.RequeiredSignatureCount, groupMemberKeys);

                PublicReviewerAddressModel model = new PublicReviewerAddressModel
                {
                    PublicApiUrl = request.PublicApiUrl
                };

                // check if the API is reachable and the address can be added to the watch list
                Uri apiRequestUri = new Uri(new Uri(model.PublicApiUrl), $"/api/WatchOnlyWallet/watch?address={scriptPubKey.Hash.GetAddress(this.network).ToString()}");
                try
                {
                    HttpWebRequest apiRequest = (HttpWebRequest)WebRequest.Create(apiRequestUri);

                    ASCIIEncoding encoding = new ASCIIEncoding();
                    string        postData = "";
                    byte[]        data     = encoding.GetBytes(postData);

                    apiRequest.Method        = "POST";
                    apiRequest.ContentType   = "application/x-www-form-urlencoded";
                    apiRequest.ContentLength = data.Length;

                    using (Stream stream = apiRequest.GetRequestStream())
                    {
                        stream.Write(data, 0, data.Length);
                    }

                    HttpWebResponse apiResponse = (HttpWebResponse)apiRequest.GetResponse();

                    string responseString = new StreamReader(apiResponse.GetResponseStream()).ReadToEnd();

                    if (apiResponse.StatusCode != HttpStatusCode.OK)
                    {
                        throw new Exception($"The API request '{apiRequestUri.ToString()}' returned the status code '{apiResponse.StatusCode}'.");
                    }
                }
                catch (Exception e)
                {
                    throw new Exception($"The API request '{apiRequestUri.ToString()}' returned an error '{e.Message}'.");
                }


                // generate the RSA keypair for the address
                AsymmetricCipherKeyPair rsaKeyPair = GetRSAKeyPairFromSeed(request.RsaPassword + scriptPubKey.Hash.GetAddress(this.network).ToString());

                RsaKeyParameters rsaPublicKey = rsaKeyPair.Public as RsaKeyParameters;
                RsaPublicKey     pbk          = new RsaPublicKey()
                {
                    Exponent = rsaPublicKey.Exponent.ToByteArrayUnsigned(),
                    Modulus  = rsaPublicKey.Modulus.ToByteArrayUnsigned()
                };

                RsaPrivateCrtKeyParameters rsaPrivateKey = rsaKeyPair.Private as RsaPrivateCrtKeyParameters;
                RsaPrivateKey prk = new RsaPrivateKey()
                {
                    DP             = rsaPrivateKey.DP.ToByteArrayUnsigned(),
                    DQ             = rsaPrivateKey.DQ.ToByteArrayUnsigned(),
                    Exponent       = rsaPrivateKey.Exponent.ToByteArrayUnsigned(),
                    Modulus        = rsaPrivateKey.Modulus.ToByteArrayUnsigned(),
                    P              = rsaPrivateKey.P.ToByteArrayUnsigned(),
                    PublicExponent = rsaPrivateKey.PublicExponent.ToByteArrayUnsigned(),
                    Q              = rsaPrivateKey.Q.ToByteArrayUnsigned(),
                    QInv           = rsaPrivateKey.QInv.ToByteArrayUnsigned()
                };

                // return all the information we have
                model = new PublicReviewerAddressModel
                {
                    Network            = this.network.ToString(),
                    Address            = scriptPubKey.Hash.GetAddress(this.network).ToString(),
                    PublicName         = request.PublicName,
                    GroupName          = request.GroupName,
                    ValidFrom          = request.ValidFrom.ToString("o"),
                    ValidUntil         = request.ValidUntil.ToString("o"),
                    ScriptPubKeyHex    = scriptPubKey.ToHex(),
                    RsaPublicKeyHex    = pbk.ToHex(),
                    RsaPrivateKeyHex   = prk.ToHex(),
                    RsaPasswordHashHex = rsaPasswordHashHex,
                    PublicApiUrl       = request.PublicApiUrl
                };

                ((WalletManager)this.walletManager).AddReviewerAddressToReviewerStore(model);

                return(this.Json(model));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }