Since you are new to the relevant technology and unfamiliar with the existing poor-quality code base you will be required to work on, it is likely that the estimation may vary to some extent in both directions. But let the client know about the latter reason :-P
First, list the myriad of changes/features your client has asked. For each requirement, do a little code review and research about how to implement and test it. You should invest this time without return before giving an estimate.
Second, make 3 columns for estimation - best case (25% probability), average case (50%), worst case (75%). For the 2 reasons mentioned in the first paragraph, you may choose the worst case estimation. You may then add even 20% buffer time. For example, for a particular requirement, your best case estimation is 2 days, average case is 4 days and worst case is 5 days. Adding 20% buffer time, your estimation is 6 days.
Third, do not give a fixed point of estimation, rather a range. For the above example, you can tell the client that the estimation is 4 to 6 days. Your client may insist on estimation for whole list of changes. In that case, you may add up the minimums and maximums of ranges for all requirements. Then provide a final estimation in range, say 5 to 6.5 months. This has the following advantage: you may exceed estimation for one requirement, but may finish another requirement earlier. In total, they cancel out each other and final estimation holds up.
Fourth, as you finish each user requirement and deliver incrementally, review your previous estimations for each requirement. This is a continuous process and you should adjust/refine the estimation as you proceed with the project and your experience grows. If you see that difference between your refined estimation and your initial estimation is out of control, sit with your client immediately and discuss the matter.
I learned these things from the book "Software Estimation : Demystifying the Black Art" by Steve McConnell. I am grateful to him.