You are not permitted to download, save or email this image. Visit image gallery to purchase the image.
Perera was not out on 153, his highest test score, as he put on 78 for the last wicket with number 11 Vishwa Fernando (six not out), taking Sri Lanka to a victory target of 304 that had looked out of sight for much of the innings.
South Africa appeared odds-on for victory when they claimed the ninth Sri Lankan wicket with the score on 226, but Perera launched a brilliant counter-attack with a mix of powerful hitting and intelligent farming of the strike.
The win, Sri Lanka's first in any format since October, ends South Africa's run of seven home series victories in a row with the second and final test in Port Elizabeth from Feb. 21-25.
"I don’t know what to say, it was a great effort as a team, the lower-order batsmen gave me great support," Perera said at the post-match presentation.
"I played my part, but we win as a team. This is a special game for us."
The winning total is the third-highest run chase ever in Durban and leaves Sri Lanka unbeaten in three tests at Kingsmead, with two wins and a draw.
South Africa were missing seamer Vernon Philander with a hamstring injury on Saturday, but the much-vaunted seam attack that had seen off Pakistan earlier in the season was expected to complete the win when Sri Lanka resumed the day on 83 for three.
Dale Steyn picked up two wickets in an over to leave the tourists on 110 for five, but Perera and Dhananjaya de Silva (48) put on 96 runs for the sixth wicket to take Sri Lanka to within a hundred of their target.
But Keshav Maharaj (3-71) removed the latter and along with Duanne Olivier (2-35) took four wickets for the addition of 20 runs to leave South Africa on the brink of what looked like being a routine victory.
But Perera, with only one previous test hundred to his name, continued to attack the bowling and, along with the stout rear-guard from Fernando, kept South Africa at bay.
The last wicket stand of 78 is the highest ever to win a first class game of cricket, while the previous highest in tests was 57 by Pakistan against Australia in 1994.
"It was an incredible game of cricket, and obviously very disappointing to be on the losing side," South Africa captain Faf du Plessis said.
"Well played to Sri Lanka, Perera was unbelievable; he deserves all the accolades that will come to him.
"Our bowlers were pretty good over the last two days, apart from a superhuman effort from Perera. I thought 300 was enough on this wicket, but great batting took it away from us."