If your URLs are pretty much all indexed both with HTTP and HTTPS, we would seriously consider just making the entire site HTTPS since you’re already going to be redirecting essentially half of your indexed URLs. HTTPS is a positive ranking factor now, and Search Metrics has seen a significant lift on sites that converted to all HTTPS.
But ONLY do this if you can do it correctly which means modifying URLs for object references like images, CSS, JS files, etc. so that they too use HTTPS. Otherwise, your site will be throwing up warnings to you visitors that the pages contain unsecure content.
We would transfer the value of the HTTP pages over to their corresponding HTTPS pages. Any slight loss of PageRank/link juice should be offset to the gains resulting from going HTTPS. Once this is done, however, all new links would be pointing directly to the HTTPS version of the site’s URLs.
A 301 will pass an assumed 95% link equity from backlinks. The only thing better is to do nothing at all, but given the duplicate content implications and over indexation and confusion from Google attempting to index both URLs, this is still a good move.
But the purpose and functionality between the two are different. In this case, a 301 says that the HTTPS page was permanently moved to HTTP – in essence the two pages are merged into one. Visitors to HTTPS are sent directly to the HTTP page. Conversely, the canonical is the same as saying “I have two identical pages, I’m aware of that, but I only want Google to pay attention to one of them”. Both pages still respond, but the proper canonical tag is your indicator to Google that you know the HTTPS and HTTP page are the same – only index the HTTP page.
The other big difference between the two is how the Google bot crawls. Once they detect a URL with a 301, they will start to not crawl that URL again. They may revisit it for a while to ensure that you didn’t accidentally add the 301. But over time they will respect the 301 and not crawl that URL anymore. If your site is large, this is a good thing. What it does is forces Google to crawl the pages you care about – Google bot only crawls so many pages each time it visits. So by ensuring it is crawling the pages you care about, it becomes more efficient, notices your site changes more quickly, and gets quicker and more accurate in how it indexes your content. Conversely, with a Canonical tag there is a far greater chance that it’ll crawl the HTTPS and HTTP pages as they are all “valid” pages. Once it sees the canonical tag on the HTTPS pages however, it will stop loading that page and move to the HTTP version (per the canonical tag). Because of this, it has a greater number of pages to continue to crawl and thus is technically less efficient. If your site isn’t very large, then that’s not a big concern. If you have a large site this is something to consider. You can always get a good feel for how much of your site they are crawling by looking at the crawl stats in Google Search Console.
In summary, both solutions will solve your issue – but depending on if you are utilizing a proper SSL and thus need HTTPS to respond with the secure encrypted response internet users are starting to expect