搜索
Table_bottom

标签云
Table_bottom

分类
Table_bottom

声明
文章若未特別註明,皆採用 知识共享许可协议 請自覺遵守
Table_bottom

存档
Table_bottom

匆匆过客
18344
Table_bottom

功能
Table_bottom

從何而來的安全

先說引子:

某日在fuubo中轉發微博,提示出錯。反復多次,皆是如此,於是上網頁版的排查。然而打開之後提示“系统检测到您的微博帐号近期存在异常,已锁定部分功能。为保障帐号安全,请立即修改密码。”如圖:

我心想:應該是因爲我在新移動設備的網頁端登錄微博,並且轉發了一個,所以說我有安全風險。那麼既然這樣,就改吧。

然後點擊了修改密碼,然而跳轉到的頁面並不是修改密碼的頁面,而是:https://security.weibo.com/rmabnormal/verifyadd

WTF!

先觀察網址:這是一個通用的頁面,而不是和我賬號直接相關的頁面。(而且其路徑也昭示了其作用。)

然後,看其中的文辭:“请填写一个有效的手机号用于验证您的身份”。

什麼叫“有效的手機號”?由上一個步驟我們知道這並不是我賬號相關的頁面,所以說並不是新浪數據庫中存儲的和我賬號相關的某個手機號。退一步說,即使這個步驟是想要依靠手機號來索引(查明)賬號,那麼也是不可能的。爲什麼?因爲我從來都沒有給新浪過我的任何手機號!我的新浪微博是使用新浪郵箱註冊的,新浪郵箱的安全通知機制是安全郵箱而並不是手機;而除了微博中公開的信息以外,我沒有在其中增加任何和我個人隱私相關的信息。

綜合下來,這個“有效的手機號”只能有一個解釋:任何人的手機號!

重新看看標題和副標題:“解除帐号异常——您的帐号存在安全风险,请按照如下流程解除异常”。莫大的諷刺:我的賬號有安全風險於是受到限制,而解除該限制的方法是使用任何一個人的手機號。換句話說:任何人都可以用這個頁面填寫手機號,然後通過驗證!

所以這究竟是爲了我賬號更安全,還是不在乎我賬號的安全?

 

這只是某風氣的一個體現而已,其所反映的是網絡上很多企業/公司在推行的一種方案:收集用戶手機號。名義上,這些公司收集用戶手機號號稱是“爲了用戶賬號安全着想”。然而是否有人想過,該做法保證的是什麼安全呢?

首先通過觀察我們可以發現,獲得用戶手機號之後,服務提供方所採取的方案分爲三種:1、在登錄時就要求手機獲取驗證碼,不正確則無法登錄(或者說兩步驗證);2、在異常時給用戶發送通知;3、在某些特定情況下(如用戶想要修改密碼時)發送驗證碼用以鑑別身份。

當然,還有第四種:只收集手機號,之後什麼功能都不提供。不過由於這種情況顯然並沒有提高安全性,所以就不討論了。

網絡賬戶涉及到的可能不安全之處有這些:1、服務提供者本身泄密;2、用戶將密碼告知並不足夠可信的他人;3、用戶在不可信之處填寫自己的賬號密碼;4、用戶所用設備有惡意軟件;5、用戶密碼過弱導致被暴力破解;6、通信鏈路中數據明文傳輸且受到截獲。

其中第一點要看服務提供方自己的能力以及素質,這點我們作爲用戶只有兩個選擇:1、相信提供商;2、不使用其服務。而受制於很多因素,一些服務我們不得不使用(如教育部將某些學生必需的服務交與一些第三方企業提供),這種情況下我們就沒有選擇了。對於這種,一個手機號(無論採取哪種方案)無能爲力。

第二點其核心問題在於用戶本身:爲什麼要將密碼告知於一個不可信的人?互聯網上的例子可能感覺不明顯,我來舉個生活中的例子:我們應該經常見到新聞中報導某人受某些因素影響(謊稱中獎、公安等)將自己銀行卡中的資金轉到騙子處。對於這種情況,即使加入手機驗證(無論1/2/3)這一步驟,用戶依然會將驗證碼交給那個人,並不能保證安全。

第三點涉及兩方:1、用戶;2、盜取信息的網站。(順便一提:在我看來,在這種途徑中用戶泄漏賬號密碼,用戶的責任至少有一半。)在用戶這邊,所看到的是一個(無論是否貌似正常的)登錄區域,於是信手將賬號密碼填入;在網站那邊,它可以獲得所有人輸入的賬號密碼,不論是否正確。看起來這時候方案1可以有效解決問題——驗證碼是一次性的,即使對方獲取到了你的賬號密碼,沒有驗證碼也無法登錄你的賬戶。然而這種想法中有一個重大漏洞:假站點如果也要求輸入驗證碼呢?假站點可以通過你給它的真實驗證碼登錄你的賬戶,然後做出一些動作(例如給其他人發消息騙取錢財之類)。而方案2對此束手無策,最多只能事後告知,之後用戶去避免損失擴大(然而需要用戶“主動”,這種“主動”對許多用戶來說是堅決不可接受的);方案3面臨的問題和1類似,甚至還不如1的效果——直到修改密碼前都可以隨意登錄。服務商要求手機在這點中起到的唯一作用(而且需要方案1)就是:提高騙子行騙的技術門檻。

第四點中惡意軟件不包含虛假登錄框(因爲這樣和第三點就一樣了),而是指那些可能竊取用戶賬號密碼的軟件。這樣的話,方案1確實可以有效解決問題(參考第三點中的分析);而方案2/3則只能事後補救,且一些用戶堅決不願意如此做。

第五點則是(無論國內國外)許多人很容易犯的一種錯誤,而且這些人無論其他人怎麼呼籲,他們都不願意去修改自己的做法,於是導致這麼多年過去依舊大有人在。在該問題中,方案1可以有效解決;方案2/3只能事後補救。(然而如果用戶不願意爲自己的賬戶安全着想而設置較複雜的密碼,那麼爲何還依然要他設置靜態密碼而不直接完全使用動態密碼呢?)

第六點問題關鍵不在用戶,而在服務提供商——明知網絡鏈路不安全,仍然明文傳輸緊要信息。(而這樣不負責人的服務商,如何能讓人相信他會爲用戶的隱私負責?如何放心將手機號交與他?)是的,方案1對此有作用,然而依靠這種方案來掩蓋自己提供服務本身的不安全實在是令人不齒,也令人心驚。方案2/3無用,無須多議。

 

綜上:方案2和方案3對於防止非法獲得賬號信息沒有幫助;方案1在3/6的情況下可以解決該安全問題。而在方案1起作用的事件中,第六點並不是應該放任不管事情,所以該狀況不應當作爲增加手機可以防止賬號信息泄漏的支持,所以實際上只有2/5的情況下可以解決問題。而第四點隨着時代(技術)發展越來越少,早已不復當年之多;第五點所涉及的那些人,指望他們意識到安全問題實在是天方夜譚,其爲了安全而主動增加手機兩步驗證也實在是難以想像的事情。所以說是2/5的情況,其實際效果遠遠比狀況比例要低。

這就完了麼?並不是。我們可以注意到:第四點談論的是惡意軟件的問題,也就是病毒、木馬等東西的問題。一個正常的計算機(是的我已經限定到windows上了)上是沒有這些惡意軟件的,而惡意軟件(在windows vista以後)在用戶合理使用計算機的情況下(保持UAC的默認開啓,不下載不受信軟件,不允許非主動開啓的軟件通過UAC權限請求)是很難存在的。我無意在這指責這些人——因爲指責也沒用——而是想到了另一個問題:他們的智能手機也可以(而且是非常可能)感染惡意軟件!是的,我們到這之前討論的都是電腦的情況,而從來沒有考慮過手機假如不安全會如何!於是我們可以想象這種情況:一個人的手機上有一個可以讀取手機號碼、讀取短信(或是僅僅接收新短信)、連接網絡、開機啓動的惡意軟件(只要這四個權限即可),而同樣是這個人在自以爲安全的情況下放心大膽地在某個地方填寫了自己的賬號密碼,而恰好這兩處惡意都是來自同一方(某甲)!於是乎,這個人的賬號密碼被某甲知道了,而且他每次收到的驗證碼某甲也都知道,於是他的賬號安全在似乎是十分安全的情況下片甲不存。

也許有人會問了:“智能手機上惡意軟件哪那麼容易感染?軟件都是系統進行調控的,有沒有都是可以看出來的。”是的軟件是系統調控的,但是你去檢查一下,看看有多少軟件一次性要許許多多權限(手機識別碼、短信、網絡、自啓動只是基礎,相當多的國產軟件都是幾乎要了一切權限)?它們有的是“大公司”產品,有的只是不明作坊的產品,而其核心問題是:源代碼都不開放,作爲用戶無人能知其究竟做了什麼。更何況,由於我朝沒有官方市場(play store),普遍使用的軟件市場中軟件來路均不明,你怎麼保證自己下載到的都是官方所發佈的版本而不是第三方修改過後僞裝的版本?你怎麼知道自己以爲無害的程序不會在後面偷偷做小動作?

不知在考慮過這種情況後是否會覺得觸目驚心呢?自以爲的安全其實根本無法保證安全,它只是把風險從一個地方移到了另一個地方而已。而不巧的是,該風險是否會存在,其僅僅視乎用戶是否有一個良好的使用習慣——其保證者之前是用戶自己,現在仍然是用戶自己!

保護自己賬號安全永遠只能靠自己:不要輕信任何人、使用更安全的密碼、不亂登錄、儘可能使用受信的軟件/服務(開源軟件)。

 

那羣公司們不可能都想不到(加入手機號能提供的安全十分有限),但一個個仍然採取各種手段或勸或騙地收集用戶的手機號,還給通信公司資金以便能夠給你發短信,其目的何在?真的只是“爲了用戶賬戶的安全”嗎?別忘了,相當多的人可是沒有給他們錢的,他們——作爲以盈利爲目的的公司——憑什麼給你投入啊。

現在人們都很喜歡談論一個說法叫大數據,而且一些(不知道資金從何而來的)媒體煽風點火說“大數據時代用戶將沒有隱私”。這種說法背後的道理在哪?就是因爲一些用戶會在各種地方留下許多自己的敏感信息,而計算機軟件可以將這些信息綜合起來,將一個人在各個地方的信息連接起來。該做法的核心在於:有共同項。如果沒有共同項,任憑現在的軟件如何收集信息,也無法將一個人在不同平臺上的信息聯繫起來。聯繫起來之後,會發生什麼就不好說了,例如將你的信息再賣給其他願意出錢買的組織啊什麼的。

這就是爲什麼一個個公司都在收集用戶的各種信息。而爲什麼手機號這麼突出?原因有兩點:1、除了身份證和姓名以外,手機號可以說是一個人最不容易變的地方了;2、用戶往往並不在意自己的手機號,覺得這是“公開”的信息。於是,這些貢獻了手機號的用戶就這麼不知不覺地把自己賣給了那些公司。典型的被賣了還幫着數錢。

 

可以展望一下,當發現現有的收集方法效果不明顯以後,各個公司們還會宣稱:爲了保護用戶賬號安全,全面啓用短信動態密碼,都去提交手機號。是的動態密碼確實有助於保護,但是如果我沒帶手機或者手機沒電的時候該怎麼登錄我的賬號?更或者手機被偷了呢?我在手機上所登錄的所有賬號怎麼辦?

再下一步,公司們應該不滿足於手機號,估計就該收集身份證號了……至於名目嘛,我也可以幫他們想好:爲了確認用戶的身份,減少詐騙現象的發生。扯淡!你作爲一個企業而不是公安部門,如何而又如何能被允許驗證我提交的身份信息是否真實?真的出於某種明目而一定要對應賬號和身份,可以,叫政府來建立和管理數據庫——我寧願相信政府(不出敗類)也不願相信這些公司(不會拿我的身份信息去做別的事情)。

 

時代變了,手段變了,而事情的本質沒變。同樣的,用戶的隱私也一直在自己手裏,只是看自己是否願意去保護。

“十目所視,十手所指,其嚴乎?”“千夫所指,無病而死。”

Python中經驗致誤處

豫:這是一篇記述自己學藝不精的文章,而不是介紹什麼奇技淫巧或是隱藏語義的。

 

Python用了也有幾個年頭了(雖然並不是全年都在用),然而發現自己還是有很多依賴(其他語言的)經驗而導致問題的地方。可能是由於自己的學習方式,也可能僅僅是由於語義的問題,這些問題也許是一些人學習中總是會遇到的(嗯,我不會說有一些同學也遇到這些問題),故且總結一下,以饗後人。

 

我個人學習Python所依賴的是:1.其他語言的經驗(Pascal/C/C++/Java);2.實踐;3.《Python學習手冊》。

是的,我沒有看《Python Cookbook》一類的(貌似更適合用來入門的)東西——不是因爲覺得沒必要,而是因爲不知道《Python學習手冊》裏邊的內容居然是那個樣子……而看完《Python學習手冊》以後就再也不想看什麼書了,實在是被它的厚度噁心到了。

 

函數參數默認值

Python中支持函數重載,也(因此而得以)支持參數默認值。

在最初用過的其他語言中,一些(C、Java)不支持重載,而支持的(C++)也沒有內置一些高級數據結構(及其便捷的初始化方法),於是從來沒有遇到過這種問題。

 

到了Python中,我想當然地以爲:參數默認值在每次函數調用的時候都是一個全新的,或者說每次重入的時候都會重新初始化一遍。

而事實上,參數默認值在每次重入時都是同一個!

 

這在簡單一些的數據結構中問題/區別不大,例如數字等不可變類型:因爲它們每次賦值時都會修改引用爲一個新的,而不是修改目標數據的值。

然而,遇到複雜數據結構/對象的時候,區別就體現出來了。我碰到的就是以一個空列表(list)爲默認值時產生的奇妙現象:在函數中每次都要修改這個列表,而由於總是同一個對象,而不是每次從一個空白的新對象開始,於是進行索引、追加等等操作時候結果總是和預期的不同。

 

意識到這個問題之後開始排查問題所在,最終鎖定到參數默認值上。經過一段搜索,搜到了這裏。其中解釋道:參數默認值僅僅在def語句被執行時會被求值。並且,其中也給出了替代的解決方案,如:使用None作爲默認值,之後在函數體中進行判斷。

 

變量作用域

按照C++的習慣,每一個區塊中的變量在出了區塊之後就失效——其中用花括號({})來界定區塊。

故而,在python中我一直以爲每個縮進層級中所創建的變量在出了該層級之後就失效。

然而在教人(之前從沒學過編程)Python時,發現居然不是這樣!當時還鬧了個笑話……

 

所以看來Python中變量作用域是整個函數,而不僅僅是聲明/賦值的那個區塊。

 

import入口

寫的某個flask程序中由於需要在整個程序中共享一些變量/對象,所以在入口的最外區塊中直接進行賦值,然後在其他部分import之。

看起來一直運行正常,然而在假如migrate的時候出事了,數據庫ORM沒有出現。排查好久終於通過id()發現其他部分所用的變量和入口處的那個不同,而它們之間相同……

於是纔意識到,入口的那些代碼在調用的時候執行一次,在import時候又執行一次,而反復import的時候不會重複執行。

是了,以前只知道反復import不會重複執行,但是從來沒意識到入口處並不是import的……

 

 

(主作於2016.3.15。拖延症……)

不知疾與無疾

我們先來說說這麼兩種人:第一種人,他們不願意去醫院看病,因爲他們可能本來覺得自己身體還不錯,如果去醫院檢查出來有病會讓他們很不舒服;第二種人,他們感到不舒服時對去醫院檢查並不排斥,並且遵守醫囑,更是還有一部分會定期去醫院做體檢。

第一種人,他們在去醫院檢查之後如果發現沒有病,就會反過來埋怨叫他檢查的人,因爲他覺得耽誤自己時間和浪費錢了;如果檢查出來有病(但並非不可醫治),同樣會去怪罪叫他去檢查的人,因爲他覺得自己本來好好的,如果不去檢查就不會發現有問題;如果檢查出來的病不可醫治,那麼他一般會一蹶不振,並且(雖然不說)在內心中怪罪叫他檢查的人,因爲他覺得自己現在要注意這個注意那個的很討厭。

第二種人,他們在去醫院檢查之後如果發現沒有病,則會感覺更加舒適,且並不會對叫他檢查的人有什麼怨言;如果檢查出來有病(但並非不可醫治),那麼會感謝叫他檢查的人,因爲他知道雖然現在需要有一些限制,但這樣自己可以好得更快,最終是對自己有益的;如果檢查出來的病不可醫治,那麼他依然會積極面對,因爲儘早發現纔能更好地對待自己的身體,遵循建議的話或許可以獲得更長的生命以及平均來講更高的生命質量。

 

這麼兩種人,在生活中應該能找到相應例子,想來諸位應該感觸頗深。一般而言,如果一個人有正常的取向,那麼他會努力去當第二種人而不是第一種人。

然而在計算機領域,這種認知似乎是顛倒的:人們普遍認爲,閉源軟件更“安全”——只因爲它的漏洞相對而言更難以發現。

 

好了我們來看看這些事情:

1. “閉源軟件的漏洞相對而言更難以發現”這句話是正確且毫無疑問的。但“更難”究竟是難多少,卻是一個難以考量的問題。至少我們可以確認一點:閉源並不是不可能被發現漏洞,否則Windows、IE等的漏洞不會被發現那麼多。

2. 人們對軟件的認知不同,於是決定了當發現某軟件的一個漏洞以後不同人會有不同的反應。一部分人認爲,軟件和硬件類似,只要獲得(安裝)了就不再變了,於是在他們的概念中,軟件的漏洞被發現得越少越好,軟件升級也只是讓他們厭煩的事情;另一部分人認爲,軟件和知識類似,擁有(安裝)了以後如果發現有問題是可以改進(升級)的,於是在他們的觀念中,軟件的漏洞發現與否並不是特別重要(或者說他們知道軟件漏洞的發現是必然的),而發現了一個漏洞以後自己的是否能及時得到升級(修復漏洞)纔是最重要的。

3. 發現軟件漏洞的人/團體在發現漏洞之後的做法也不盡相同,大致也可分爲兩類。第一類發現之後會去報告,然後軟件的“生產”方“可能”會花一些時間去修正這個問題,再花一些時候之後將問題的補丁放出;第二類發現之後自己利用漏洞而不去報告,於是漏洞直到有第一類人報告纔有可能會得到修復。

 

由如上諸點,加上開源閉源本身的特性,我們可以得到下面的推論:

1. 一般而言閉源軟件比開源軟件的漏洞更難被發現。

2. 被發現漏洞後,開源軟件有更大的可能性會更快得到修復。原因有三:

1. 會爲閉源軟件找漏洞的一般有兩類人,分別是開發者僱用的人和想找漏洞的人——其中第一種會上報且有希望修復最終(希望)不會造成危害,第二種有一部分不會上報從而可能造成危害;而開源軟件也會有這兩種人——只不過一般而言第一種會少一些,而第二種好人會更多一些,其原因一是開源軟件可以享有下面一條的好處,二是開源軟件“製造”者大多不是公司(公司的本質是追逐利益)。

2. 有一點是開源軟件所有而閉源軟件沒有的:充沛的同儕審查。同儕這裏指任何有興趣的開發者——由於我們可以相信世界上好人多,開發者也是好人多,所以這一部分人會有較高機率會去上報。而且由於源代碼公開,他們很有希望可以直接提出解決方案,而不用等待原始開發者自己再去還原產生環境、查找、修復。在這種睽睽衆目之下,軟件漏洞難以遁形,於是我們可以假設有1個惡意的想找漏洞的人,而有9個善意的想找漏洞的人,有極大的概率使得9個人中有人找到漏洞且修復,而那1個還沒有找到。

3. 開源軟件開發一般都是逐步增長的,即所謂“集市”模式(顯然閉源軟件無法採取這種模式)。這樣,在一個軟件還沒有特別多用戶羣的時候,它的許多基礎問題已經被解決。而且在用戶羣逐步增長的過程中,其新版本加入的內容也在不斷地被驗證確認,本身引入問題的可能性就低;而即使引入問題,由於有許多其他人可以檢查,遇到的問題也會較快地被解決,不用等到像閉源軟件普遍的已經產生大量用戶羣以後再發現、解決。

3. 閉源會給軟件編寫者一種虛假的支配安全感:軟件有錯誤也無所謂,反正除了我們沒人知道。於是在這種心理下,開發者更容易寫出質量較差的代碼,其中產生問題的可能性也更高。反觀開源這邊,因爲一切都是公開進行的,所以開發者一般都會對自己代碼質量有較高要求(不論是出於面子還是什麼),而且即使出現了質量不大高的代碼,其他有空的人也可以對它進行改進,避免小問題最終釀成大禍。

4. 除了被“入侵”這點以外,安全還有兩個層面:

1. 保證用戶的數據安全。閉源軟件由除了其開發者以外沒人能接觸到源代碼,所以如果其中有哪一部分可能會工作不正常而導致數據損壞,開發者只有兩個途徑知道:一是自我審查或者測試的時候發現;二是事情出現以後有用戶報告。如果等到用戶報告,那麼就太晚了。而開源軟件由於代碼公開,所以在審查代碼(無論是自己還是任一一個人)時被發現的可能性要高很多,而且更由於可以有大量的人參與討論,這類問題的修復速度也會比閉源軟件高。

2. 保證用戶本身的安全,尤其是保護用戶隱私。在這一點上,閉源軟件絲毫沒有可信度——看不到源代碼,你說你沒做手腳誰信啊;而開源軟件由於源代碼公開,所以用戶可以放心使用。(嚴格說來,如果一個公司想要在軟件上做些什麼不可告人的事,即使將源代碼公開也可以耍些手段,例如寫得極其晦澀難懂。然而即使真的晦澀難懂也不怕,開源保證了總有人可以依照其原理寫出清晰易懂的,而且用戶們可以不怎麼費勁地切換到新的上面。)

 

這裏還有一些人會有迷思,會認爲如果一個軟件本身就和安全相關,那麼就不應該開源。爲什麼呢?他們的理由是:不公開的東西看起來似乎更不容易被攻破。然而這實際上是對安全的誤解以及對權力的服從而產生的結論。

首先我們必須明確一件事:無論一個系統(加密方法)是否公開,它的安全性是固定的。公開與否改變的是它的問題/漏洞被發現的概率,而不是漏洞是否存在——就類似上面關於去醫院檢查的例子,去檢查能改變的只是你是否知道自己有病,而不能改變你是否病。

然後一種加密技術在被大規模使用以前,是需要有一個檢驗階段的。如果在檢驗階段發現較大漏洞,那麼該技術是顯然不可採用的。如果公開,則全世界有興趣的人都可以對它進行檢驗——甚至是原理上的檢驗——如果存在問題則很快會被發現,可以免造成更嚴重的影響。而如果不公開,則只有開發者(或許還有其委託的少量幾個人)知道其原理,而其他人無法知道,從而在檢驗階段少了很多被尋找到漏洞的可能性。我們知道所有加密方式都有破解方案的——不然怎麼解密——只是被發現的難度不同而已。於是當一個有漏洞的加密方案被大規模應用(例如軍事),而後有人發現其有漏洞於是自己使用,這時候造成的危害實在是不堪設想。

口說無憑,不過現代密碼學就是我的憑證。現代密碼學的基礎原理決定了:其上的加密算公開並不會導致加密效果減弱,反而因爲有大量的同儕評審,不好的算法可以儘早被發現被廢棄。例如多數人都見過卻不一定知道是什麼的AES、RSA算法等就都是現代密碼學產物,而它們(還有相關的其他東西)在計算機世界尤其是網絡世界幾乎是作爲基礎存在的。

 

所以最後一個迷思也被攻破了,那麼作爲正常人作爲用戶,我們是不是應該很明確答案了?

閉源不會爲自己帶來任何好處,而開源至少可以保證個人隱私。所以,爲什麼不從內心中選擇開源?

 

附:

從心中選擇開源不是說要立即把所有的東西都換成類似的開源軟件——當然這樣做很好,但總會遇到各種各樣問題——而是要有意識地去考慮:“某個軟件有沒有相同質量的開源代替物?某個軟件有沒有可能開源,至少讓它開放API以讓人們可以開發開源客戶端?某個開源軟件的設計爲什麼和我用的相同功能的另一個軟件差別那麼大,排除習慣因素,究竟哪個設計更好?”

春節好?不,你叫錯了

(本文是個人對所瞭解到的一些事情所進行的總結,如有錯誤還望不吝指正。)

在當代人們的心中,中國傳統的新年叫做“春節”,而且似乎也沒什麼問題——過年時總是在春天前後,而且“寒假”是冬天到春天的過渡期,而寒假的具體時間總是和新年相關。
然而很不幸,大家都被誤導了。

本文大約結構:首先拆穿錯誤,其次說明錯誤肇始,最後給出正確。

(爲了跟大家解釋清楚本文主題,這裏不得不先捋一下曆法的問題。)
人們一般都知道這麼一個常識:中國傳統的新年是夏曆(文革後亦稱農曆)的正月初一(順便一提,生肖也是按夏曆正月初一——而不是公曆——變換的,今天CCTV-1晚間新聞幹得不錯),而夏曆和公曆並不一樣,甚至一年的長短都不同。然而由於某些原因,人們往往將夏曆錯誤地稱爲“陰曆”,而又將公曆稱爲“陽曆”,然後就理所當然地認爲既然一陰一陽肯定不同,而沒有去仔細思考。
事實上,夏曆並不是什麼陰曆。(不過公曆確實是陽曆沒錯。)
所謂“陰曆”、“陽曆”,分別是“太陰曆”、“太陽曆”的簡稱。“太陽”是什麼,大家都知道;而“太陰”這麼個說法可能有些陌生,不過一些人可能腦子轉得比較快,應該能想到就是月亮。搞清了太陰、太陽,也就好弄懂什麼是太陰曆、太陽曆了:太陰曆(lunar calendar)指以太陰(月)的運轉(週期)爲根據而制定的曆法,例如伊斯蘭曆;太陽曆(solar calendar)指以太陽(日)的運轉(週期)爲根據而制定的曆法,例如格里高利曆(當今公曆)。有些人看到這可能會在腹誹:夏曆的每個月就是根據太陰的運轉而制定的,你前邊卻說它不是太陰曆,騙誰呢?各位請稍安勿躁,這裏請出另一尊大神來解決大家的疑惑:陰陽合曆。所謂陰陽合曆(lunisolar calendar),就是指同時考慮太陽和太陰的運轉而制定的曆法。而我們的夏曆,就屬於陰陽合曆。(再舉個陰陽合曆的例子:猶太曆。)
又有人要腹誹了:你說它是陰陽合曆,你告訴我說它“陽”的部分在哪啊?好,來大家想一想小學時期是不是背過這麼一口訣:春雨驚春清穀天……沒錯,二十四節氣!是不是有人當年還奇怪過:明明節氣和公曆上的“月+日”有一定對應關係,卻說它是中國傳統的東西?事情的關鍵就在這:二十四節氣正是夏曆中陽的一部分,而每個月則是其中陰的一部分。如果有人仍不願相信,那麼再來考慮這麼一個問題:大家都知道華夏是農耕文明,而對農業來說顯然地日關係比地月關係更爲要緊,那麼這麼樣一個文明的曆法可能會不考慮太陽運轉(“科學”的說法是地球公轉)麼?可能嗎?
大家知道,地日週期是365日餘不足366日,而地月週期是29日餘不足30日,無論如何無法得到一個整數使得地月週期乘上它得到地日週期,即:若以月球公轉週期爲月份長度,無法直接滿足地球公轉週期。那麼以太陰運轉定月份長度的夏曆,是如何保證其陰陽合曆的本質呢?這回您猜對了:閏月。

好了,說清了夏曆的本質後,新年這個問題就好講了。既然夏曆中的一年和地球繞太陽公轉的一年長度並不相同,那麼很顯然,每年的正月初一時地球並不處於公轉中的同一位置。這也就是我們站在公曆的角度看,每年過年的時間都不同的原因。好我們翻翻公元2000年開始到今年(公元2016年)的日曆,傳統新年最早(最接近冬至)的是甲申新年(癸未大寒次日/2004年1月22日),最晚的是乙未新年(乙未雨水當日/2015年2月19日)。這兩個新年之間相差接近一月,跨了冬春兩季,如何當得起“春節”之稱?

當然了,我們無法否認現今階段華夏新年被稱爲“春節”。那麼我們就再來翻一翻歷史,看看華夏新年究竟是何時被稱爲“春節”的。如果這件事要我來做,那估計是要在我寫好一個趁手軟件之後再來的了。所幸已有前輩做過完善的整理,我們來看看前輩是如何說的:(節選自溪山琴況所作之文《正月飞雪庭燎光,元夕笙动春未央》)
“新年称为‘春节’的说法从何而来?说起来,这倒是一个不及百年、并不久远的故事。
……
1912年1月2日,孙中山发布《临时大总统改历改元通电》:‘中华民国改用阳历,以黄帝纪元四千六百九年十一月十三日,为中华民国元年元旦。经由各省代表团议决,由本总统颁行。订定于阳历正月十五日,补祝新年。请布告。孙文。’
……
风云突变,袁氏登上历史舞台。内务总长、登极大典筹备处长朱启钤于1914年1月21日提出《定四时节假呈》:‘拟请:定阴历元旦为春节,端午为夏节,中秋为秋节,冬至为冬节。凡我国民均得休息,在公人员亦准给假一日,本部为顺从民意起见,是否有当?理合呈请大总统鉴核施行。’袁世凯旋即批准。从此,夏历元旦被降格为一个季节性节日,‘春节’,而与中国文化毫无关系的西历岁首被称为‘元旦’和‘新年’,成为官方倡导的法定新年。
然而,民间信仰和习惯的力量是强大的。无论官方如何倡导新历新年,百姓并不买帐,民间仍然把夏历元旦当成最隆重盛大的新年来过。洋派的当权者终于按捺不住,一场‘废除春节’的闹剧在1930年上演。
1930年底,南京国民政府颁令‘废除春节’。
……
文化的传统再一次表现出强大的延续力量。虽然政客煞有介事地组织了各种‘国历新年’的活动,但官员多敷衍行事,民间也是消极抵制。相反,到了夏历新年时,民众仍然偷偷过年。几年后,‘国历新年’的活动逐渐销声匿迹,国人如常地过着除夕、元旦,‘废除春节’的闹剧无疾而终。一代代的政客已成尘土,但是‘春节’的概念却在不知不觉中在民众的心中植根,近百年来,几成新的‘传统’。回味略显苦涩,我们至今守着的,竟是袁世凯造出的概念,他留给国人几乎唯一的‘遗产’。”
而“春節”這麼一個似乎頗爲順口的稱呼,本來是在指代什麼呢?繼續援引溪山琴況文:“中国是一个岁时节日丰富的国度,也许是因为四季的节日太多了的缘故,华夏文化中,并不喜欢以某个特定的节日作为一个季节节日的代表,‘春节’、‘夏节’、‘秋节’、‘冬节’的说法在漫长的历史中稀疏少见,夏历的岁首……称为新年。古人偶用‘春节’时,所指为节气之首的立春。”

那麼傳統新年究竟應該叫什麼呢?如果各位讀上面那段文字時有過留心,便會發現其中有兩句甚是耐人尋味:“……定阴历元旦为……”;“……国人如常地过着除夕、元旦……”。按照通行的觀點,“元旦”乃是公曆一月一日,爲何這裏明明在說傳統節日,卻在用“元旦”的稱呼?聰明之人應當已經想到:“元旦”本就是對該日子的稱呼。
對於“元旦”這麼兩個字,《說文解字》中是這麼解釋的:“元,始也”;“旦,明也”。“元”的意義很明瞭,就是“開始”、“初始”;而“旦”則要稍稍考究一下字源了。仍然是《說文解字》中“旦”之一字:“從日見一上。”什麼意思呢?就是說“旦”這個字所表達的是:太陽(日)已從地平線(一)上升起可被人看到。我們用一個白話詞語來表達:初生(當然未必是“初”,也可能是“復”)。兩個字弄明白了,由它們構成的詞(字組)意義也就明瞭了:歲首(初始日)出現(初生)之時,也就是指每年的第一天(或按夏曆的說法叫“正月初一”)。
我知道:所有人看到這裏,都已看懂“元旦”便是指曆法中第一天,而且在中國的語境下特指夏曆正月初一;但是並非所有人都願意去修正自己的說法,因爲自己已經“習慣”了叫公曆一月一號爲“元旦”而叫夏曆正月初一爲“春節”。無外乎溪山琴況前輩在文中嘆息道:“‘春天的节日’成了安置华夏新年的单薄的躯壳,名已不正,言已不顺,多少年了,中国在漫天飞雪中过着‘春天的节日’,而别人的新年,已经被叫做代表岁时之首、新年起点的‘元旦’。”

行文至此,若是英語文章,則有可能會用一句“last but not least”來收尾例舉;而我想說的,卻或許可表達爲“last but at least”——至少最後請聽我一言:不求諸位將夏曆正月初一叫做“元旦”,因爲畢竟還有個公曆一月一日要被稱呼;只求諸位將夏曆正月初一叫做“新年”而不要叫做“春節”——至少叫它“新年”並沒有什麼障礙,而且它真的不是“春天的節日”。

請和我說“新年快樂”,而不要說“新春快樂”。

孤華
乙未臘月廿八

本文遵循CC-BY-SA協議(https://creativecommons.org/licenses/by-sa/3.0/cn/deed.zh)傳播(中文可另考http://creativecommons.net.cn/licenses/meet-the-licenses/),轉載請註明作者、出處(http://renyuneyun.is-programmer.com/2016/2/7/chinese_new_year.194929.html)及是否有修改。